UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
HierarchicalSpatialHash.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "Chaos/Box.h"
5#include "Chaos/Vector.h"
6#include "Containers/Map.h"
9
10#include <atomic>
11
12namespace Chaos
13{
14template<typename PayloadType>
16{
17private:
18 struct FPayloadAndBounds
19 {
20 PayloadType Payload;
21 int32 BoundsLookupIdx;
22 };
23
24 struct FHashIndex
25 {
26 VectorRegister4Int VectorIndex;
27
28 FHashIndex() = default;
29
30 FHashIndex(const TVec3<int32>& Cell, int32 Lod)
31 :VectorIndex(MakeVectorRegisterInt(Cell.X, Cell.Y, Cell.Z, Lod))
32 {}
33 FHashIndex(int32 CellX, int32 CellY, int32 CellZ, int32 Lod)
34 :VectorIndex(MakeVectorRegisterInt(CellX, CellY, CellZ, Lod))
35 {}
36 FHashIndex(const VectorRegister4Int& InVectorIndex)
37 :VectorIndex(InVectorIndex)
38 {}
39
40 bool operator==(const FHashIndex& Other) const
41 {
42 union
43 {
46 }Result;
47 Result.i = VectorIntCompareNEQ(VectorIndex, Other.VectorIndex);
48 return VectorMaskBits(Result.v) == 0;
49 }
50
51 inline uint32 GetTypeHash() const
52 {
53 // xorHash
54 static constexpr VectorRegister4Int Multiplier = MakeVectorRegisterIntConstant(73856093, 19349663, 83492791, 67867979);
58 return (uint32)(Indexable[0] ^ Indexable[1] ^ Indexable[2] ^ Indexable[3]);
59 }
60 };
61
62 // This hashmap is designed to be fast at just what we need to do to build all at once in exactly the order it is done in Initialize and then query.
63 // Based off of Core/HashTable.h
64 class FHashMap
65 {
66 public:
67 void Reset()
68 {
69 Hash.Reset();
70 Elements.Reset();
71 }
72
73 void PreallocateElementsForConcurrentAdd(int32 MaxNumElements, int32 HashSize)
74 {
75 HashSize = FMath::RoundUpToPowerOfTwo(HashSize);
76 Hash.SetNumUninitialized(HashSize);
77 for (std::atomic<int32>& H : Hash)
78 {
79 H.store(INDEX_NONE, std::memory_order_relaxed);
80 }
81 Elements.SetNumUninitialized(MaxNumElements);
82 ConcurrentElementAddIdx.store(0);
83 }
84
85 void ConcurrentAddElementRange(const TVec3<int32>& MinCellIdx, const TVec3<int32>& MaxCellIdx, int32 Lod, const FPayloadAndBounds& Value)
86 {
87 const int32 NumElementsToAdd = (MaxCellIdx[0] - MinCellIdx[0] + 1) * (MaxCellIdx[1] - MinCellIdx[1] + 1) * (MaxCellIdx[2] - MinCellIdx[2] + 1);
88
90 {
91 int32 IndexToWrite = ConcurrentElementAddIdx.fetch_add(NumElementsToAdd, std::memory_order_relaxed);
92
93 for (int32 XIdx = MinCellIdx[0]; XIdx <= MaxCellIdx[0]; ++XIdx)
94 {
95 for (int32 YIdx = MinCellIdx[1]; YIdx <= MaxCellIdx[1]; ++YIdx)
96 {
97 for (int32 ZIdx = MinCellIdx[2]; ZIdx <= MaxCellIdx[2]; ++ZIdx)
98 {
99 FElement Element;
100 Element.Key = FHashIndex(XIdx, YIdx, ZIdx, Lod);
101 const uint32 HashKey = Element.Key.GetTypeHash() & (Hash.Num() - 1);
102 Element.NextIndex = Hash[HashKey].load(std::memory_order_relaxed);
103 while (!Hash[HashKey].compare_exchange_weak(Element.NextIndex, IndexToWrite, std::memory_order_release, std::memory_order_relaxed));
104 Element.Value = Value;
105 Elements[IndexToWrite] = MoveTemp(Element);
106 ++IndexToWrite;
107 }
108 }
109 }
110 }
111 }
112
113 int32 ConcurrentAddElement(const TVec3<int32>& CellIdx, int32 Lod, const FPayloadAndBounds& Value)
114 {
115 const int32 IndexToWrite = ConcurrentElementAddIdx.fetch_add(1, std::memory_order_relaxed);
116 FElement Element;
117 Element.Key = FHashIndex( CellIdx, Lod );
118 const uint32 HashKey = Element.Key.GetTypeHash() & (Hash.Num() - 1);
119 Element.NextIndex = Hash[HashKey].load(std::memory_order_relaxed);
120 while (!Hash[HashKey].compare_exchange_weak(Element.NextIndex, IndexToWrite, std::memory_order_release, std::memory_order_relaxed));
121 Element.Value = Value;
122 Elements[IndexToWrite] = MoveTemp(Element);
123
124 return IndexToWrite;
125 }
126
127 void ShrinkElementsAfterConcurrentAdd()
128 {
129 Elements.SetNum(ConcurrentElementAddIdx.load(), EAllowShrinking::No);
130 }
131
132 int32 First(const FHashIndex& Key) const
133 {
135 const uint32 HashKey = Key.GetTypeHash() &(Hash.Num() - 1);
136 return Hash[HashKey].load(std::memory_order_relaxed);
137 }
138
139 int32 Next(int32 Index) const
140 {
141 return Elements[Index].NextIndex;
142 }
143
144 static bool IsValid(int32 Index)
145 {
146 return Index != INDEX_NONE;
147 }
148
149 bool KeyMatches(int32 Index, const FHashIndex& Key) const
150 {
151 return Elements[Index].Key == Key;
152 }
153
154 const FPayloadAndBounds& GetValue(int32 Index) const
155 {
156 return Elements[Index].Value;
157 }
158
159 const FHashIndex& GetKey(int32 Index) const
160 {
161 return Elements[Index].Key;
162 }
163
164 private:
165
167 struct FElement
168 {
169 FHashIndex Key;
170 FPayloadAndBounds Value;
171 int32 NextIndex;
172 };
173
174 TArray<FElement> Elements;
175 std::atomic<int32> ConcurrentElementAddIdx;
176 };
177
178 FHashMap HashMap;
179
180 void Reset()
181 {
182 HashMap.Reset();
183 }
184
185 static inline TVec3<int32> CellIdxForPoint(const VectorRegister4Float& Point, const VectorRegister4Float& CellSize)
186 {
187 VectorRegister4Float Tmp = VectorDivide(Point, CellSize);
188
193 return TVec3<int32>(Result4[0], Result4[1], Result4[2]);
194 }
195
196 static inline TVec3<int32> CellIdxForPoint(const VectorRegister4Double& Point, const VectorRegister4Double& CellSize)
197 {
199
204 return TVec3<int32>(Result4[0], Result4[1], Result4[2]);
205 }
206
207 template<typename PT, typename T> friend class THierarchicalSpatialHash;
208 template<typename PT, typename T> friend class TSpatialHashGridPoints;
209};
210
211// Currently this assumes a 3 dimensional grid.
212template<typename PayloadType, typename T>
214{
216 using typename Base::FPayloadAndBounds;
217 using typename Base::FHashMap;
218 using typename Base::FHashIndex;
219 using Base::HashMap;
220
221 static int32 LodForCellSize(T CellSize)
222 {
223 // want Ceil( log2(CellSize) )
224 if (CellSize <= (T).5)
225 {
226 return -(int32)FMath::FloorLog2((uint32)FMath::FloorToInt32((T)1 / CellSize));
227 }
228 else
229 {
230 return (int32)FMath::CeilLogTwo((uint32)FMath::CeilToInt32(CellSize));
231 }
232 }
233
234 static T CellSizeForLod(const int32 Lod)
235 {
236 if (Lod >= 0)
237 {
238 return (T)(1ULL << Lod);
239 }
240 return (T)1 / (T)(1ULL << (-Lod));
241 }
242
243public:
244
246 {
247 public:
248
249 FVectorAABB() = default;
250
251 explicit FVectorAABB(const TAABB<T, 3>& BBox)
252 : Min(MakeVectorRegister(BBox.Min()[0], BBox.Min()[1], BBox.Min()[2], (T)0.))
253 , Max(MakeVectorRegister(BBox.Max()[0], BBox.Max()[1], BBox.Max()[2], (T)0.))
254 {}
255
256 explicit FVectorAABB(const TVec3<T>& Point)
257 : Min(MakeVectorRegister(Point[0], Point[1], Point[2], (T)0.))
258 , Max(Min)
259 {}
260
261 FVectorAABB(const TVec3<T>& Point, const T Radius)
262 : Min(MakeVectorRegister(Point[0], Point[1], Point[2], (T)0.))
263 , Max(Min)
264 {
265 Thicken(Radius);
266 }
267
269 {
271 Min = VectorMin(Min, Vector);
272 Max = VectorMax(Max, Vector);
273 }
274
275 void GrowToInclude(const TVec3<T>& Point, const T Radius)
276 {
278 const TVectorRegisterType<T> ThicknessVec = MakeVectorRegister(Radius, Radius, Radius, (T)0);
281 }
282
283 void Thicken(const T Thickness)
284 {
285 const TVectorRegisterType<T> ThicknessVec = MakeVectorRegister(Thickness, Thickness, Thickness, (T)0);
286 Min = VectorSubtract(Min, ThicknessVec);
287 Max = VectorAdd(Max, ThicknessVec);
288 }
289
291 {
293 TVec3<T> Extents;
295 return Extents.Max();
296 }
297
298 const TVectorRegisterType<T>& GetMin() const { return Min; }
299 const TVectorRegisterType<T>& GetMax() const { return Max; }
300
301 bool Intersects(const FVectorAABB& Other) const
302 {
303 if (VectorAnyLesserThan(Other.Max, Min) || VectorAnyGreaterThan(Other.Min, Max))
304 {
305 return false;
306 }
307 return true;
308 }
309
311 {
313 {
314 return false;
315 }
316 return true;
317 }
318
319 private:
320
323 };
324
325 void Reset()
326 {
327 Base::Reset();
328 UsedLods.Reset();
329 }
330
331 template<typename ParticlesType>
332 void Initialize(const ParticlesType& Particles, const T MinLodSize = (T)0)
333 {
335 Reset();
336
337 Bounds.SetNumUninitialized(Particles.Num());
338 HashMap.PreallocateElementsForConcurrentAdd(Particles.Num() * 8, Particles.Num() * 2);
339
340 const int32 MinAllowableLod = MinLodSize > (T)0 ? LodForCellSize(MinLodSize) : std::numeric_limits<int32>::min();
341
342 // For most common UsedLods, store whether or not the Lod is used in an array without a lock.
343 // For uncommon Lods, use a critical section to store directly into the UsedLods map.
344 constexpr int32 MaxPreAllocatedUsedLodValue = 10; // i.e., a single element 2^10 = 1024 across
345 constexpr int32 MinPreAllocatedUsedLodValue = -10; // i.e., a single element 1 / (2^10) ~= 0.001 across.
347 memset(UsedLodsArray.GetData(), 0, UsedLodsArray.Num() * sizeof(bool));
349
350 PhysicsParallelFor(Particles.Num(),
352 {
353 const auto& Particle = Particles[ParticleIdx];
354 const FVectorAABB ParticleBounds = Particle.VectorAABB();
355
356 const int32 Lod = FMath::Max(MinAllowableLod, LodForCellSize(ParticleBounds.LongestSideLength()));
357 const T CellSize = CellSizeForLod(Lod);
358 const TVectorRegisterType<T> CellSizeVector = MakeVectorRegister(CellSize, CellSize, CellSize, CellSize);
359
360 const PayloadType Payload = Particle.template GetPayload<PayloadType>(ParticleIdx);
361
362 const TVec3<int32> MinCellIdx = Base::CellIdxForPoint(ParticleBounds.GetMin(), CellSizeVector);
363 const TVec3<int32> MaxCellIdx = Base::CellIdxForPoint(ParticleBounds.GetMax(), CellSizeVector);
364
365 const FPayloadAndBounds Value = { Payload, ParticleIdx };
366 HashMap.ConcurrentAddElementRange(MinCellIdx, MaxCellIdx, Lod, Value);
367
368 Bounds[ParticleIdx] = ParticleBounds;
370 {
372 }
373 else
374 {
376 UsedLods.Add(Lod, CellSize);
378 }
379 }
380 );
381
382 HashMap.ShrinkElementsAfterConcurrentAdd();
383
385 {
387 {
388 UsedLods.Add(Lod, CellSizeForLod(Lod));
389 }
390 }
391 }
392
394 TFunctionRef<bool(const int32 Payload)> BroadphaseTest) const
395 {
396 // LookupBounds intentionally passed by value--it seems faster if it gets copied locally.
397 TArray<PayloadType> Result;
398 for (const typename TMap<int32, T>::ElementType& UsedLod : UsedLods)
399 {
400 const int32 Lod = UsedLod.Key;
401 const TVectorRegisterType<T> CellSize = MakeVectorRegister(UsedLod.Value, UsedLod.Value, UsedLod.Value, UsedLod.Value);
402
403 const TVec3<int32> MinCellIdx = Base::CellIdxForPoint(LookupBounds.GetMin(), CellSize);
404 const TVec3<int32> MaxCellIdx = Base::CellIdxForPoint(LookupBounds.GetMax(), CellSize);
405
406 for (int32 XIdx = MinCellIdx[0]; XIdx <= MaxCellIdx[0]; ++XIdx)
407 {
408 for (int32 YIdx = MinCellIdx[1]; YIdx <= MaxCellIdx[1]; ++YIdx)
409 {
410 for (int32 ZIdx = MinCellIdx[2]; ZIdx <= MaxCellIdx[2]; ++ZIdx)
411 {
412 const FHashIndex Key{ {XIdx, YIdx, ZIdx}, Lod };
413 for (int32 HashIndex = HashMap.First(Key); HashMap.IsValid(HashIndex); HashIndex = HashMap.Next(HashIndex))
414 {
415 if (HashMap.KeyMatches(HashIndex, Key))
416 {
417 const FPayloadAndBounds& Value = HashMap.GetValue(HashIndex);
418 if (!BroadphaseTest(Value.Payload))
419 {
420 continue;
421 }
422
423 const FVectorAABB& PayloadBounds = Bounds[Value.BoundsLookupIdx];
424
425 if (PayloadBounds.Intersects(LookupBounds))
426 {
427 // Typical cloth examples do not find a lot of unique results.
428 // In testing, the overhead to do this search is lower than using a TSet and converting the result to an array
429 Result.AddUnique(Value.Payload);
430 }
431 }
432 }
433 }
434 }
435 }
436 }
437 return Result;
438 }
439
441 {
442 return FindAllIntersections(FVectorAABB(LookupBounds), [](const int32) { return true; });
443 }
444
446 {
448
449 TArray<PayloadType> Result;
450 for (const typename TMap<int32, T>::ElementType& UsedLod : UsedLods)
451 {
452 const int32 Lod = UsedLod.Key;
453 const TVectorRegisterType<T> CellSize = MakeVectorRegister(UsedLod.Value, UsedLod.Value, UsedLod.Value, UsedLod.Value);
454
455 const TVec3<int32> CellIdx = Base::CellIdxForPoint(PointVec, CellSize);
456 const FHashIndex Key{ CellIdx, Lod };
457 for (int32 HashIndex = HashMap.First(Key); HashMap.IsValid(HashIndex); HashIndex = HashMap.Next(HashIndex))
458 {
459 if (HashMap.KeyMatches(HashIndex, Key))
460 {
461 const FPayloadAndBounds Value = HashMap.GetValue(HashIndex);
462 const FVectorAABB& PayloadBounds = Bounds[Value.BoundsLookupIdx];
463
464 if (PayloadBounds.Intersects(PointVec))
465 {
466 // Typical cloth examples do not find a lot of unique results.
467 // In testing, the overhead to do this search is lower than using a TSet and converting the result to an array
468 Result.AddUnique(Value.Payload);
469 }
470 }
471 }
472 }
473 return Result;
474 }
475
476private:
477
478 TMap<int32, T> UsedLods;
479 TArray<FVectorAABB> Bounds;
480};
481
482template<typename PayloadType, typename T>
484{
486 using typename Base::FPayloadAndBounds;
487 using typename Base::FHashMap;
488 using typename Base::FHashIndex;
489 using Base::HashMap;
490
491public:
496
497 void Reset()
498 {
499 Base::Reset();
500 ParticleIndexToElement.Reset();
501 }
502
503 template<typename ParticlesType>
504 void InitializePoints(const ParticlesType& Particles, bool bForceSingleThreaded = false)
505 {
507 Reset();
508
509 ParticleIndexToElement.SetNum(Particles.Num());
510 HashMap.PreallocateElementsForConcurrentAdd(Particles.Num(), Particles.Num());
511 PhysicsParallelFor(Particles.Num(),
512 [this, &Particles](int32 ParticleIdx)
513 {
514 const auto& Particle = Particles[ParticleIdx];
515 const PayloadType Payload = Particle.template GetPayload<PayloadType>(ParticleIdx);
516 const auto& ParticleX = Particle.X();
517 const TVec3<int32> CellIdx = Base::CellIdxForPoint(MakeVectorRegister(ParticleX[0], ParticleX[1], ParticleX[2], 0), CellSize);
518 const FPayloadAndBounds Value = { Payload, ParticleIdx };
519 const int32 ElementIdx = HashMap.ConcurrentAddElement(CellIdx, INDEX_NONE, Value);
520 ParticleIndexToElement[ParticleIdx] = ElementIdx;
522 );
523
524 HashMap.ShrinkElementsAfterConcurrentAdd();
525 }
526
528 {
529 check(CellRadius >= 0);
530
531 // Working around MSVC lambda bug with this functor.
533 {
534 const int32 CellRadius;
535 TFunctionRef<bool(const int32 Payload0, const int32 Payload1)> NarrowTest;
536 const FHashMap& HashMap;
537 const TArray<int32>& ParticleIndexToElement;
538
539 // Resize using a RWLock. Start with MaxNumExpectedConnections
541 std::atomic<int32> ResultIndex;
542 std::atomic<int32> CurrentResultNum; // Arrays aren't thread-safe, so use this to track size instead.
544
546 TFunctionRef<bool(const int32 Payload0, const int32 Payload1)> InNarrowTest,
547 const FHashMap& InHashMap, const TArray<int32>& InParticleIndexToElement)
548 :CellRadius(InCellRadius), NarrowTest(InNarrowTest), HashMap(InHashMap), ParticleIndexToElement(InParticleIndexToElement), ResultIndex(0)
549 {
550 Result.SetNum(InMaxNumExpectedConnections);
551 Result.SetNum(Result.Max()); // Remove all slack.
552 CurrentResultNum.store(Result.Num());
553 }
554
555 void AddResult(const TVec2<PayloadType>& Proximity)
556 {
557 if (!NarrowTest(Proximity[0], Proximity[1]))
558 {
559 return;
560 }
561 const int32 NewResultIndex = ResultIndex.fetch_add(1);
562 if (NewResultIndex < CurrentResultNum.load())
563 {
564 ResultResizeRWLock.ReadLock();
565 Result[NewResultIndex] = Proximity;
566 ResultResizeRWLock.ReadUnlock();
567 }
568 else
569 {
570 ResultResizeRWLock.WriteLock();
571 if (NewResultIndex >= CurrentResultNum.load())
572 {
573 // Use array's allocator to decide how much slack to create
574 Result.SetNum(NewResultIndex + 1);
575 Result.SetNum(Result.Max());
576 CurrentResultNum.store(Result.Num());
577 }
578 Result[NewResultIndex] = Proximity;
579 ResultResizeRWLock.WriteUnlock();
580 }
581 }
582
583 void AddResultsInCell(PayloadType ThisPayload, const FHashIndex& Cell)
584 {
585 for (int32 HashIndex = HashMap.First(Cell); HashMap.IsValid(HashIndex); HashIndex = HashMap.Next(HashIndex))
586 {
587 if (HashMap.KeyMatches(HashIndex, Cell))
588 {
589 AddResult(TVec2<PayloadType>(ThisPayload, HashMap.GetValue(HashIndex).Payload));
590 }
591 }
592 }
593
594 void operator()(int32 ParticleIdx)
595 {
596 const int32 ThisElementIdx = ParticleIndexToElement[ParticleIdx];
597 const int32 ThisPayload = HashMap.GetValue(ThisElementIdx).Payload;
598 const FHashIndex& ThisKey = HashMap.GetKey(ThisElementIdx);
599
600 // All neighbors in our cell after us in the list
601 int32 OtherElementIdx = HashMap.Next(ThisElementIdx);
602 for (; HashMap.IsValid(OtherElementIdx); OtherElementIdx = HashMap.Next(OtherElementIdx))
603 {
604 if (HashMap.KeyMatches(OtherElementIdx, ThisKey))
605 {
606 AddResult(TVec2<PayloadType>(ThisPayload, HashMap.GetValue(OtherElementIdx).Payload));
607 }
608 }
609
610 // Iterate over cells within CellRadius away. Only look "forward". Particles behind us will find us by looking forward.
611 // I dunno... there's probably a better way to do this.....
612 for (int32 ZIndex = 1; ZIndex <= CellRadius; ++ZIndex)
613 {
614 AddResultsInCell(ThisPayload, FHashIndex(VectorIntAdd(ThisKey.VectorIndex, MakeVectorRegisterInt(0, 0, ZIndex, 0))));
615 }
616
617 for (int32 YIndex = 1; YIndex <= CellRadius; ++YIndex)
618 {
620 {
622 }
623 }
624
625 for (int32 XIndex = 1; XIndex <= CellRadius; ++XIndex)
626 {
628 {
630 {
632 }
633 }
634 }
635
636 }
637
638 } ConcurrentResults{ CellRadius, MaxNumExpectedConnections, NarrowTest, HashMap, ParticleIndexToElement };
639
640 PhysicsParallelFor(ParticleIndexToElement.Num(), ConcurrentResults, bForceSingleThreaded);
641
642 // Shrink Result array to actual number of found proximities
643 const int32 ResultNum = ConcurrentResults.ResultIndex.load();
645 return ConcurrentResults.Result;
646 }
647private:
648 const TVectorRegisterType<T> CellSize;
649
650 // Particle Index is dense array index passed in at build time.
651 TArray<int32> ParticleIndexToElement;
652};
653}
654
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define ensureAlways( InExpression)
Definition AssertionMacros.h:466
#define check(expr)
Definition AssertionMacros.h:314
@ INDEX_NONE
Definition CoreMiscDefines.h:150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define TRACE_CPUPROFILER_EVENT_SCOPE(Name)
Definition CpuProfilerTrace.h:528
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
const bool
Definition NetworkReplayStreaming.h:178
@ Multiplier
FORCEINLINE VectorRegister4Int MakeVectorRegisterInt(int32 X, int32 Y, int32 Z, int32 W)
Definition UnrealMathFPU.h:282
FORCEINLINE VectorRegister4Float VectorSubtract(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:731
FORCEINLINE uint32 VectorAnyGreaterThan(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1917
FORCEINLINE VectorRegister4Float VectorMin(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1686
#define VectorShiftRightImmArithmetic(Vec, ImmAmt)
Definition UnrealMathFPU.h:2659
FORCEINLINE VectorRegister4Float MakeVectorRegister(uint32 X, uint32 Y, uint32 Z, uint32 W)
Definition UnrealMathFPU.h:195
FORCEINLINE void VectorIntStoreAligned(const VectorRegister4Int &A, const void *Ptr)
Definition UnrealMathFPU.h:2578
FORCEINLINE VectorRegister4Int VectorIntCompareNEQ(const VectorRegister4Int &A, const VectorRegister4Int &B)
Definition UnrealMathFPU.h:2365
FORCEINLINE VectorRegister4Float VectorDivide(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:834
FORCEINLINE VectorRegister4Float VectorMax(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:1713
FORCEINLINE VectorRegister4Int VectorRoundToIntHalfToEven(const VectorRegister4Float &A)
Definition UnrealMathFPU.h:2175
FORCEINLINE constexpr VectorRegister4Int MakeVectorRegisterIntConstant(int32 X, int32 Y, int32 Z, int32 W)
Definition UnrealMathFPU.h:292
FORCEINLINE int32 VectorMaskBits(const VectorRegister4Float &Vec1)
Definition UnrealMathFPU.h:1075
FORCEINLINE VectorRegister4Float VectorAdd(const VectorRegister4Float &Vec1, const VectorRegister4Float &Vec2)
Definition UnrealMathFPU.h:704
FORCEINLINE void VectorIntStore(const VectorRegister4Int &A, const void *Ptr)
Definition UnrealMathFPU.h:2546
FORCEINLINE VectorRegister4Int VectorIntMultiply(const VectorRegister4Int &A, const VectorRegister4Int &B)
Definition UnrealMathFPU.h:2435
FORCEINLINE VectorRegister4Int VectorIntAdd(const VectorRegister4Int &A, const VectorRegister4Int &B)
Definition UnrealMathFPU.h:2417
FORCEINLINE void VectorStoreFloat3(const VectorRegister4Float &Vec, float *Dst)
Definition UnrealMathFPU.h:594
FORCEINLINE VectorRegister4Float MakeVectorRegisterFloatFromDouble(const VectorRegister4Double &Vec4d)
Definition UnrealMathFPU.h:262
FORCEINLINE uint32 VectorAnyLesserThan(VectorRegister4Float Vec1, VectorRegister4Float Vec2)
Definition UnrealMathVectorCommon.h.inl:450
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
typename UE::Math::VectorRegisterPrivate::TVectorRegisterTypeHelper< T >::Type TVectorRegisterType
Definition VectorRegister.h:49
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition AABB.h:37
Definition HierarchicalSpatialHash.h:246
void Thicken(const T Thickness)
Definition HierarchicalSpatialHash.h:283
T LongestSideLength() const
Definition HierarchicalSpatialHash.h:290
bool Intersects(const FVectorAABB &Other) const
Definition HierarchicalSpatialHash.h:301
void GrowToInclude(const TVec3< T > &Point, const T Radius)
Definition HierarchicalSpatialHash.h:275
FVectorAABB(const TVec3< T > &Point)
Definition HierarchicalSpatialHash.h:256
void GrowToInclude(const TVec3< T > &Point)
Definition HierarchicalSpatialHash.h:268
FVectorAABB(const TVec3< T > &Point, const T Radius)
Definition HierarchicalSpatialHash.h:261
const TVectorRegisterType< T > & GetMax() const
Definition HierarchicalSpatialHash.h:299
FVectorAABB(const TAABB< T, 3 > &BBox)
Definition HierarchicalSpatialHash.h:251
const TVectorRegisterType< T > & GetMin() const
Definition HierarchicalSpatialHash.h:298
bool Intersects(const TVectorRegisterType< T > &Point) const
Definition HierarchicalSpatialHash.h:310
Definition HierarchicalSpatialHash.h:214
void Initialize(const ParticlesType &Particles, const T MinLodSize=(T) 0)
Definition HierarchicalSpatialHash.h:332
TArray< PayloadType > FindAllIntersections(const TAABB< T, 3 > &LookupBounds) const
Definition HierarchicalSpatialHash.h:440
TArray< PayloadType > FindAllIntersections(const TVec3< T > &Point) const
Definition HierarchicalSpatialHash.h:445
TArray< PayloadType > FindAllIntersections(const FVectorAABB LookupBounds, TFunctionRef< bool(const int32 Payload)> BroadphaseTest) const
Definition HierarchicalSpatialHash.h:393
void Reset()
Definition HierarchicalSpatialHash.h:325
Definition HierarchicalSpatialHash.h:16
Definition HierarchicalSpatialHash.h:484
TSpatialHashGridPoints(const T InCellSize)
Definition HierarchicalSpatialHash.h:492
void Reset()
Definition HierarchicalSpatialHash.h:497
TArray< TVec2< PayloadType > > FindAllSelfProximities(int32 CellRadius, int32 MaxNumExpectedConnections, TFunctionRef< bool(const int32 Payload0, const int32 Payload1)> NarrowTest, bool bForceSingleThreaded=false) const
Definition HierarchicalSpatialHash.h:527
void InitializePoints(const ParticlesType &Particles, bool bForceSingleThreaded=false)
Definition HierarchicalSpatialHash.h:504
Definition Vector.h:1000
FORCEINLINE T Max() const
Definition Vector.h:1070
Definition Vector.h:41
Definition Array.h:670
Definition AssetRegistryState.h:50
Definition UnrealString.h.inl:34
Definition StaticArray.h:26
Definition CriticalSection.h:14
Definition SkeletalMeshComponent.h:307
void CHAOS_API PhysicsParallelFor(int32 InNum, TFunctionRef< void(int32)> InCallable, bool bForceSingleThreaded=false)
Definition Parallel.cpp:55
constexpr VectorRegister4Double DoubleOneHalf
Definition UnrealMathVectorConstants.h.inl:68
constexpr VectorRegister4Float FloatOneHalf
Definition UnrealMathVectorConstants.h.inl:50
float v
Definition radaudio_mdct.cpp:62
U16 Index
Definition radfft.cpp:71
static constexpr UE_FORCEINLINE_HINT bool IsPowerOfTwo(T Value)
Definition UnrealMathUtility.h:519
Definition UnrealMathFPU.h:42
Definition UnrealMathFPU.h:20
Definition UnrealMathFPU.h:28