UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PBDRigidsSOAs.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
7
8namespace Chaos
9{
10namespace CVars
11{
14}
15
16// A helper function to get the debug name for a particle or "UNKNOWN" when debug names are unavailable
17template<typename TParticleType>
18const FString& GetParticleDebugName(const TParticleType& Particle)
19{
20#if CHAOS_DEBUG_NAME
21 return *Particle.DebugName();
22#else
23 static const FString SNoDebugNames = TEXT("<UNKNOWN>");
24 return SNoDebugNames;
25#endif
26}
27
29{
30public:
31 virtual ~IParticleUniqueIndices() = default;
33 virtual void ReleaseIdx(FUniqueIdx Unique) = 0;
34};
35
37{
38public:
40 : Block(0)
41 {
42 //Note: tune this so that all allocation is done at initialization
43 AddPageAndAcquireNextId(/*bAcquireNextId = */ false);
44 }
45
47 {
48 while(true)
49 {
50 if(FUniqueIdx* Idx = FreeIndices.Pop())
51 {
52 return *Idx;
53 }
54
55 //nothing available so try to add some
56
57 if(FPlatformAtomics::InterlockedCompareExchange(&Block,1,0) == 0)
58 {
59 //we got here first so add a new page
60 FUniqueIdx RetIdx = FUniqueIdx(AddPageAndAcquireNextId(/*bAcquireNextId =*/ true));
61
62 //release blocker. Note: I don't think this can ever fail, but no real harm in the while loop
63 while(FPlatformAtomics::InterlockedCompareExchange(&Block,0,1) != 1)
64 {
65 }
66
67 return RetIdx;
68 }
69 }
70 }
71
73 {
74 ensure(Unique.IsValid());
75 int32 PageIdx = Unique.Idx / IndicesPerPage;
76 int32 Entry = Unique.Idx % IndicesPerPage;
77 FUniqueIdxPage& Page = *Pages[PageIdx];
78 FreeIndices.Push(&Page.Indices[Entry]);
79 }
80
82 {
83 //Make sure queue is empty, memory management of actual pages is handled automatically by TUniquePtr
84 while(FreeIndices.Pop())
85 {
86 }
87 }
88
89private:
90
91 int32 AddPageAndAcquireNextId(bool bAcquireNextIdx)
92 {
93 //Note: this should never really be called post initialization
95 const int32 PageIdx = Pages.Num();
96 int32 FirstIdxInPage = PageIdx * IndicesPerPage;
97 Page->Indices[0] = FUniqueIdx(FirstIdxInPage);
98
99 //If we acquire next id we avoid pushing it into the queue
100 for(int32 Count = bAcquireNextIdx ? 1 : 0; Count < IndicesPerPage; Count++)
101 {
103 FreeIndices.Push(&Page->Indices[Count]);
104 }
105
106 Pages.Emplace(MoveTemp(Page));
108 }
109
110 static constexpr int32 IndicesPerPage = 1024;
111 struct FUniqueIdxPage
112 {
113 FUniqueIdx Indices[IndicesPerPage];
114 };
117 volatile int8 Block;
118};
119
121
127template <typename TParticleType>
129{
130public:
132 : ContainerListMask(EGeometryParticleListMask::None)
133 {
134 }
135
136 void Reset()
137 {
138 ParticleToIndex.Reset();
139 ParticleArray.Reset();
140 }
141
142 bool Contains(const TParticleType* Particle) const
143 {
144 return ParticleToIndex.Contains(Particle);
145 }
146
147 template <typename TParticle1>
149 {
152
153 // TODO: Compile time check ensuring TParticle2 is derived from TParticle1?
154 int32 NextIdx = ParticleArray.Num();
155 for (int32 Idx = 0; Idx < ParticlesToInsert.Num(); ++Idx)
156 {
157 auto Particle = ParticlesToInsert[Idx];
158 Contains[Idx] = ParticleToIndex.Contains(Particle);
159 if (!Contains[Idx])
160 {
161 ParticleToIndex.Add(Particle, NextIdx++);
162 }
163 }
164 ParticleArray.Reserve(ParticleArray.Num() + NextIdx - ParticleArray.Num());
165 for (int32 Idx = 0; Idx < ParticlesToInsert.Num(); ++Idx)
166 {
167 if (!Contains[Idx])
168 {
169 auto Particle = ParticlesToInsert[Idx];
170 ParticleArray.Add(Particle);
171 }
172 }
173 }
174
175 void Insert(TParticleType* Particle)
176 {
177 if (ParticleToIndex.Contains(Particle) == false)
178 {
179 ParticleToIndex.Add(Particle, ParticleArray.Num());
180 ParticleArray.Add(Particle);
181 }
182 }
183
184 void Remove(TParticleType* Particle)
185 {
186 if (int32* IdxPtr = ParticleToIndex.Find(Particle))
187 {
188 int32 Idx = *IdxPtr;
189 ParticleArray.RemoveAtSwap(Idx);
190 if (Idx < ParticleArray.Num())
191 {
192 //update swapped element with new index
193 ParticleToIndex[ParticleArray[Idx]] = Idx;
194 }
195 ParticleToIndex.Remove(Particle);
196 }
197 }
198
200 {
202 Ar << SerializableArray;
203
204 int32 Idx = 0;
205 for (auto Particle : ParticleArray)
206 {
207 ParticleToIndex.Add(Particle, Idx++);
208 }
209 }
210
211 const TArray<TParticleType*>& GetArray() const { return ParticleArray; }
212 TArray<TParticleType*>& GetArray() { return ParticleArray; }
213
214 void SetContainerListMask(const EGeometryParticleListMask InMask) { ContainerListMask = InMask; }
215 EGeometryParticleListMask GetContainerListMask() const { return ContainerListMask; }
216
217private:
218 TMap<TParticleType*, int32> ParticleToIndex;
219 TArray<TParticleType*> ParticleArray;
220 EGeometryParticleListMask ContainerListMask;
221};
222
228template <typename TParticleType>
230{
231public:
233 : ContainerListMask(EGeometryParticleListMask::None)
234 {
235 }
236
237 void Reset()
238 {
239 ParticleArray.Reset();
240 }
241
242 bool Contains(const TParticleType* Particle) const
243 {
244 return ParticleArray.Contains(Particle);
245 }
246
247 void Insert(TParticleType* Particle)
248 {
249 ParticleArray.Add(Particle);
250 }
251
252 void Remove(TParticleType* Particle)
253 {
254 ParticleArray.Remove(Particle);
255 }
256
257 const TArray<TParticleType*>& GetArray() const { return ParticleArray; }
258 TArray<TParticleType*>& GetArray() { return ParticleArray; }
259
260 void SetContainerListMask(const EGeometryParticleListMask InMask) { ContainerListMask = InMask; }
261 EGeometryParticleListMask GetContainerListMask() const { return ContainerListMask; }
262
263private:
264 TArray<TParticleType*> ParticleArray;
265 EGeometryParticleListMask ContainerListMask;
266};
267
269{
270public:
272 : UniqueIndices(InUniqueIndices)
273 {
274#if CHAOS_DETERMINISTIC
276#endif
277
278 StaticParticles = MakeUnique<FGeometryParticles>();
279 StaticDisabledParticles = MakeUnique<FGeometryParticles>();
280
281 KinematicParticles = MakeUnique<FKinematicGeometryParticles>();
282 KinematicDisabledParticles = MakeUnique<FKinematicGeometryParticles>();
283
284 DynamicDisabledParticles = MakeUnique<FPBDRigidParticles>();
285 DynamicParticles = MakeUnique<FPBDRigidParticles>();
286 DynamicKinematicParticles = MakeUnique<FPBDRigidParticles>();
287
288 ClusteredParticles = MakeUnique<FPBDRigidClusteredParticles>();
289
290 GeometryCollectionParticles = MakeUnique<TPBDGeometryCollectionParticles<FReal, 3>>();
291
292 SetContainerListMasks();
293
294 UpdateViews();
295 }
296
299
301 {
302 // Abandonning the particles, don't worry about ordering anymore.
303 ClusteredParticles->RemoveParticleBehavior() = ERemoveParticleBehavior::RemoveAtSwap;
304 GeometryCollectionParticles->RemoveParticleBehavior() = ERemoveParticleBehavior::RemoveAtSwap;
305 }
306
307 void Reset()
308 {
309 check(0);
310 }
311
313 {
314 StaticParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
315 StaticDisabledParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
316
317 KinematicParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
318 KinematicDisabledParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
319
320 DynamicDisabledParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
321 DynamicParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
322 DynamicKinematicParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
323
324 ClusteredParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
325
326 GeometryCollectionParticles->ShrinkArrays(MaxSlackFraction, MinSlack);
327 }
328
330 {
331 // @todo(chaos): this should only refresh views that may have changed
332 UpdateViews();
333 }
334
336 {
337 LLM_SCOPE_BYNAME(TEXT("Physics/StaticParticles"));
338
339 auto Results = CreateParticlesHelper<FGeometryParticleHandle>(NumParticles, ExistingIndices, Params.bDisabled ? StaticDisabledParticles : StaticParticles, Params);
340 UpdateViews();
341 return Results;
342 }
344 {
345 LLM_SCOPE_BYNAME(TEXT("Physics/KinematicParticles"));
346
347 auto Results = CreateParticlesHelper<FKinematicGeometryParticleHandle>(NumParticles, ExistingIndices, Params.bDisabled ? KinematicDisabledParticles : KinematicParticles, Params);
348 UpdateViews();
349 return Results;
350 }
352 {
353 LLM_SCOPE_BYNAME(TEXT("Physics/DynamicParticles"));
354
355 auto Results = CreateParticlesHelper<FPBDRigidParticleHandle>(NumParticles, ExistingIndices, Params.bDisabled ? DynamicDisabledParticles : DynamicParticles, Params);;
356
357 if (!Params.bStartSleeping)
358 {
359 AddToActiveArray(Results);
360 }
361 UpdateViews();
362 return Results;
363 }
365 {
366 LLM_SCOPE_BYNAME(TEXT("Physics/GeometryCollectionParticles"));
367
369 NumParticles, ExistingIndices, GeometryCollectionParticles, Params);
370 for (auto* Handle : Results)
371 {
372 if (Params.bStartSleeping)
373 {
374 Handle->SetObjectStateLowLevel(Chaos::EObjectStateType::Sleeping);
375 Handle->SetSleeping(true);
376 }
377 else
378 {
379 Handle->SetObjectStateLowLevel(Chaos::EObjectStateType::Dynamic);
380 Handle->SetSleeping(false);
381 }
382 if (!Params.bDisabled)
383 {
385 }
386 }
387 UpdateViews();
388
389 return Results;
390 }
391
394 {
395 LLM_SCOPE_BYNAME(TEXT("Physics/ClusteredParticles"));
396
397 auto NewClustered = CreateParticlesHelper<FPBDRigidClusteredParticleHandle>(NumParticles, ExistingIndices, ClusteredParticles, Params);
398
399 if (!Params.bDisabled)
400 {
401 InsertClusteredParticles(NewClustered);
402 }
403
404 if (!Params.bStartSleeping)
405 {
406 AddToActiveArray(reinterpret_cast<TArray<FPBDRigidParticleHandle*>&>(NewClustered));
407 }
408
409 UpdateViews();
410
411 return NewClustered;
412 }
413
415 {
416 TransientDirtyMapArray.Reset();
417 }
418
419 // @todo(chaos): keep track of which views may be dirty and lazily update them
420 // rather than calling UpdateViews all the time
422 {
424 {
425 //if active it's already in the dirty view
426 if (!ActiveParticlesMapArray.Contains(Rigid) && !MovingKinematicsMapArray.Contains(Rigid))
427 {
428 AddToList(Rigid, TransientDirtyMapArray);
429
430 CheckParticleViewMask(Particle);
431
432 if (bUpdateViews)
433 {
434 UpdateViews();
435 }
436 }
437 }
438 }
439
441 {
442 if (bResimulating)
443 {
444 RemoveFromList(Particle, ResimStaticParticles);
446 if (Kinematic)
447 {
448 RemoveFromList(Kinematic, ResimKinematicParticles);
449 }
450 }
451
453
454 auto PBDRigid = Particle->CastToRigidParticle();
455 if(PBDRigid)
456 {
457 if (bResimulating)
458 {
459 RemoveFromList(PBDRigid, ResimDynamicParticles);
460 RemoveFromList(PBDRigid, ResimDynamicKinematicParticles);
461 }
462
463 RemoveFromActiveArray(PBDRigid, /*bStillDirty=*/ false);
464 RemoveFromList(PBDRigid, MovingKinematicsMapArray);
465
467 {
469 }
471 {
472 RemoveClusteredParticle(PBDRigidClustered);
473 }
474
475 // Check for sleep events referencing this particle
476 // TODO think about this case more
479
480 SleepData.RemoveAllSwap([Particle](TSleepData<FReal, 3>& Entry)
481 {
482 return Entry.Particle == Particle;
483 });
484
486 }
487
488 ParticleHandles.DestroyHandleSwap(Particle);
489
490 UpdateViews();
491 }
492
497 {
498 // Rigid particles express their disabled state with a boolean.
499 // Disabled kinematic and static particles get shuffled to different SOAs.
500
501 if (auto PBDRigid = Particle->CastToRigidParticle())
502 {
503 PBDRigid->SetDisabled(true);
504 PBDRigid->SetVf(FVec3f(0));
505 PBDRigid->SetWf(FVec3f(0));
506
508 {
510 }
512 {
513 RemoveClusteredParticle(PBDRigidClustered);
514 }
515 else
516 {
518 }
519
520 // All active particles RIGID particles
521 {
522 RemoveFromActiveArray(PBDRigid, /*bStillDirty=*/false);
524 {
525 RemoveFromList(PBDRigid, MovingKinematicsMapArray);
526 }
527 }
528 }
529 else if (Particle->CastToKinematicParticle())
530 {
531 Particle->MoveToSOA(*KinematicDisabledParticles);
532 }
533 else
534 {
535 Particle->MoveToSOA(*StaticDisabledParticles);
536 }
537
538 CheckParticleViewMask(Particle);
539
540 UpdateViews();
541 }
542
544 {
545 // Rigid particles express their disabled state with a boolean.
546 // Disabled kinematic and static particles get shuffled to differnt SOAs.
547
548 if (auto PBDRigid = Particle->CastToRigidParticle())
549 {
550 PBDRigid->SetDisabled(false);
551 // DisableParticle() zeros V and W. We do nothing here and assume the client
552 // sets appropriate values.
553
555 {
558 }
560 {
561 InsertClusteredParticle(PBDRigidClustered);
562 }
563 else
564 {
566 }
567
568 if (!PBDRigid->Sleeping() && Particle->ObjectState() == EObjectStateType::Dynamic)
569 {
570 AddToActiveArray(PBDRigid);
571 }
572 }
573 else if (Particle->CastToKinematicParticle())
574 {
575 Particle->MoveToSOA(*KinematicParticles);
576 }
577 else
578 {
579 Particle->MoveToSOA(*StaticParticles);
580 }
581
582 CheckParticleViewMask(Particle);
583
584 UpdateViews();
585 }
586
591 {
592 if (auto PBDRigid = Particle->CastToRigidParticle())
593 {
594 if (PBDRigid->ObjectState() == EObjectStateType::Sleeping ||
595 PBDRigid->ObjectState() == EObjectStateType::Dynamic)
596 {
597 if (ensure(!PBDRigid->Disabled()))
598 {
599 // Sleeping state is currently expressed in 2 places...
600 PBDRigid->SetSleeping(false);
601 PBDRigid->SetObjectStateLowLevel(EObjectStateType::Dynamic);
602
604 {
607 }
608 check(PBDRigid->ObjectState() == EObjectStateType::Dynamic);
609 AddToActiveArray(PBDRigid);
610
611 CheckParticleViewMask(Particle);
612
614 {
615 UpdateViews();
616 }
617 }
618 }
619 }
620 }
621
626 {
627 for (auto Particle : Particles)
628 {
629 ActivateParticle(Particle, true);
630 }
631
632 UpdateViews();
633 }
634
642 FGeometryParticleHandle* Particle,
643 const bool DeferUpdateViews=false)
644 {
645 if(auto PBDRigid = Particle->CastToRigidParticle())
646 {
647 if (PBDRigid->ObjectState() == EObjectStateType::Dynamic ||
648 PBDRigid->ObjectState() == EObjectStateType::Sleeping)
649 {
650 if (ensure(!PBDRigid->Disabled()))
651 {
652 // Sleeping state is currently expressed in 2 places...
653 PBDRigid->SetSleeping(true);
654 PBDRigid->SetObjectStateLowLevel(EObjectStateType::Sleeping);
655
657 {
660 }
661 RemoveFromActiveArray(PBDRigid, /*bStillDirty=*/true);
662
663 CheckParticleViewMask(Particle);
664
665 if (!DeferUpdateViews)
666 {
667 UpdateViews();
668 }
669 }
670 }
671 }
672 }
673
678 {
679 for (auto Particle : Particles)
680 {
681 DeactivateParticle(Particle, true);
682 }
683 UpdateViews();
684 }
685
690 {
691 UpdateViews();
692 }
693
695 {
696 const EObjectStateType State = Particle->ObjectState();
697
698 if (Particle->Disabled())
699 {
700 Particle->MoveToSOA(*DynamicDisabledParticles);
701 RemoveFromActiveArray(Particle->CastToRigidParticle(), /*bStillDirty=*/ false);
703 {
704 RemoveFromList(Particle, MovingKinematicsMapArray);
705 }
706 }
707 else
708 {
709 if (Particle->ObjectState() != EObjectStateType::Dynamic)
710 {
711 RemoveFromActiveArray(Particle->CastToRigidParticle(), /*bStillDirty=*/true);
712 }
713 else
714 {
715 AddToActiveArray(Particle->CastToRigidParticle());
716 }
717
718 if (Particle->ObjectState() != EObjectStateType::Kinematic)
719 {
720 RemoveFromList(Particle, MovingKinematicsMapArray);
721 }
722
723 if (Particle->Type == EParticleType::Clustered)
724 {
725 Particle->MoveToSOA(*ClusteredParticles);
726 if (bResimulating)
727 {
728 RemoveFromList(Particle, ResimDynamicKinematicParticles);
729 AddToList(Particle, ResimDynamicParticles);
730 }
731 }
732 else if (Particle->Type == EParticleType::GeometryCollection)
733 {
734 Particle->MoveToSOA(*GeometryCollectionParticles);
735 if (bResimulating)
736 {
737 RemoveFromList(Particle, ResimDynamicKinematicParticles);
738 AddToList(Particle, ResimDynamicParticles);
739 }
740 }
741 else
742 {
743 // Move to appropriate dynamic SOA
744 switch (State)
745 {
747 Particle->MoveToSOA(*DynamicKinematicParticles);
748 if (bResimulating)
749 {
750 RemoveFromList(Particle, ResimDynamicParticles);
751 AddToList(Particle, ResimDynamicKinematicParticles);
752 }
753 break;
754
756 Particle->MoveToSOA(*DynamicParticles);
757 if (bResimulating)
758 {
759 RemoveFromList(Particle, ResimDynamicKinematicParticles);
760 AddToList(Particle, ResimDynamicParticles);
761 }
762 break;
763
764 default:
765 // TODO: Special SOAs for sleeping and static particles?
766 Particle->MoveToSOA(*DynamicParticles);
767 if (bResimulating)
768 {
769 RemoveFromList(Particle, ResimDynamicKinematicParticles);
770 AddToList(Particle, ResimDynamicParticles);
771 }
772 break;
773 }
774 }
775 }
776
777 CheckParticleViewMask(Particle);
778
779 UpdateViews();
780 }
781
783 {
785 {
786 RemoveFromList(ClusteredParticle, MovingKinematicsMapArray);
787 }
788
790 {
791 // Geometry collection particles have their own arrays which are also included in the active view
794 }
795 else
796 {
798 RemoveClusteredParticle(ClusteredParticle);
799 InsertClusteredParticle(ClusteredParticle);
800 }
801
802 // Cluster particle must go in the active array because the Cluster arrays are not in the active view
803 if (ClusteredParticle->ObjectState() != EObjectStateType::Dynamic || ClusteredParticle->Disabled())
804 {
805 RemoveFromActiveArray(ClusteredParticle->CastToRigidParticle(), /*bStillDirty=*/true);
806 }
807 else
808 {
809 AddToActiveArray(ClusteredParticle->CastToRigidParticle());
810 }
811
812 CheckParticleViewMask(ClusteredParticle);
813
814 UpdateViews();
815 }
816
818 {
820 {
821 AddToList(Rigid, MovingKinematicsMapArray);
822 // Remove from TransientDirtyMapArray to be sure not have have particle in both lists
823 RemoveFromList(Rigid, TransientDirtyMapArray);
824
825 CheckParticleViewMask(Particle);
826 }
827 }
828
830 {
831 // moving kinematics are going to a 'reset' mode then a 'none' mode
832 // 'reset' ones need to stay for another frame
833 // 'none' can be safely removed from the map/array
834 int32 Index = 0;
835 while (Index < MovingKinematicsMapArray.GetArray().Num())
836 {
837 if (MovingKinematicsMapArray.GetArray()[Index]->KinematicTarget().GetMode() == EKinematicTargetMode::None)
838 {
839 // remove and do not increment Index
840 FPBDRigidParticleHandle* Rigid = MovingKinematicsMapArray.GetArray()[Index];
841 RemoveFromList(Rigid, MovingKinematicsMapArray);
842
843 // Particle may not be moving, but its velocity was just changed (to zero), so it
844 // needs to be in a dirty list. Since it are no longer in MovingKinematicsMapArray
845 // we must put it the transient dirty list
847
848 CheckParticleViewMask(Rigid);
849 }
850 else
851 {
852 ++Index;
853 }
854 }
855 }
856
858 {
859 static const FName SOAsName = TEXT("PBDRigidsSOAs");
861
862 ParticleHandles.Serialize(Ar);
863
864 Ar << StaticParticles;
865 Ar << StaticDisabledParticles;
866 Ar << KinematicParticles;
867 Ar << KinematicDisabledParticles;
868 Ar << DynamicParticles;
869 Ar << DynamicDisabledParticles;
870 // TODO: Add an entry in UObject/ExternalPhysicsCustomObjectVersion.h when adding these back in:
871 //Ar << ClusteredParticles;
872 //Ar << GeometryCollectionParticles;
873
876 {
877 Ar << DynamicKinematicParticles;
878 }
879
880 {
881 //need to assign indices to everything
882 auto AssignIdxHelper = [&](const auto& Particles)
883 {
884 for(uint32 ParticleIdx = 0; ParticleIdx < Particles->Size(); ++ParticleIdx)
885 {
886 FUniqueIdx Unique = UniqueIndices.GenerateUniqueIdx();
887 Particles->UniqueIdx(ParticleIdx) = Unique;
888 Particles->GTGeometryParticle(ParticleIdx)->SetUniqueIdx(Unique);
889 }
890 };
891
898 //AssignIdxHelper(ClusteredParticles);
899 //AssignIdxHelper(GeometryCollectionParticles);
900 }
901
902 ensure(ClusteredParticles->Size() == 0); //not supported yet
903 //Ar << ClusteredParticles;
904 Ar << GeometryCollectionParticles;
905
906 ActiveParticlesMapArray.Serialize(Ar);
907 //DynamicClusteredMapArray.Serialize(Ar);
908
909 //todo: update deterministic ID
910
911 // We do not serialize the list masks to simplify maintenance
912 if (Ar.IsLoading())
913 {
914 SetContainerListMasks();
915 }
916
917 //if (!GeometryCollectionParticles || !GeometryCollectionParticles->Size())
918 UpdateViews();
919 //else
920 // UpdateGeometryCollectionViews();
921 }
922
923
924 const TParticleView<FGeometryParticles>& GetNonDisabledView() const { return NonDisabledView; }
925
926 const TParticleView<FPBDRigidParticles>& GetNonDisabledDynamicView() const { return NonDisabledDynamicView; }
927
928 const TParticleView<FPBDRigidClusteredParticles>& GetNonDisabledClusteredView() const { return NonDisabledClusteredView; }
929
930 const TParticleView<FPBDRigidParticles>& GetActiveParticlesView() const { return ActiveParticlesView; }
932
933 const TArray<FPBDRigidParticleHandle*>& GetActiveParticlesArray() const { return ActiveParticlesMapArray.GetArray(); }
934
935 const TParticleView<FPBDRigidParticles>& GetDirtyParticlesView() const { return DirtyParticlesView; }
937
938 const TParticleView<FGeometryParticles>& GetAllParticlesView() const { return AllParticlesView; }
939
940
941 const TParticleView<FKinematicGeometryParticles>& GetActiveKinematicParticlesView() const { return ActiveKinematicParticlesView; }
943
944 const TParticleView<FPBDRigidParticles>& GetActiveMovingKinematicParticlesView() const { return ActiveMovingKinematicParticlesView; }
945 TParticleView<FPBDRigidParticles>& GetActiveMovingKinematicParticlesView() { return ActiveMovingKinematicParticlesView; }
946
947 const TParticleView<FGeometryParticles>& GetActiveStaticParticlesView() const { return ActiveStaticParticlesView; }
949
950 const TParticleView<FPBDRigidParticles>& GetActiveDynamicMovingKinematicParticlesView() const { return ActiveDynamicMovingKinematicParticlesView; }
951 TParticleView<FPBDRigidParticles>& GetActiveDynamicMovingKinematicParticlesView() { return ActiveDynamicMovingKinematicParticlesView; }
952
953 const TGeometryParticleHandles<FReal, 3>& GetParticleHandles() const { return ParticleHandles; }
955
956 const FPBDRigidParticles& GetDynamicParticles() const { return *DynamicParticles; }
957 FPBDRigidParticles& GetDynamicParticles() { return *DynamicParticles; }
958
959 const FPBDRigidParticles& GetDynamicKinematicParticles() const { return *DynamicKinematicParticles; }
960 FPBDRigidParticles& GetDynamicKinematicParticles() { return *DynamicKinematicParticles; }
961
962 // Disabled Dynamic and DynamicKinematic Particles
963 const FPBDRigidParticles& GetDynamicDisabledParticles() const { return *DynamicDisabledParticles; }
964 FPBDRigidParticles& GetDynamicDisabledParticles() { return *DynamicDisabledParticles; }
965
966 const FGeometryParticles& GetNonDisabledStaticParticles() const { return *StaticParticles; }
967 FGeometryParticles& GetNonDisabledStaticParticles() { return *StaticParticles; }
968
969 const TPBDGeometryCollectionParticles<FReal, 3>& GetGeometryCollectionParticles() const { return *GeometryCollectionParticles; }
971
972 const TArray<FPBDGeometryCollectionParticleHandle*>& GetSleepingGeometryCollectionArray() const { return SleepingGeometryCollectionArray.GetArray(); }
973 const TArray<FPBDGeometryCollectionParticleHandle*>& GetDynamicGeometryCollectionArray() const { return DynamicGeometryCollectionArray.GetArray(); }
974
976 {
977 if (!GCParticle->Disabled())
978 {
979 const Chaos::EObjectStateType State = GCParticle->Sleeping() ? Chaos::EObjectStateType::Sleeping : GCParticle->ObjectState();
980 switch (State)
981 {
983 ensure(false); // we should probably not be here
984 break;
986 AddToList(GCParticle, StaticGeometryCollectionArray);
987 break;
989 AddToList(GCParticle, KinematicGeometryCollectionArray);
990 break;
992 AddToList(GCParticle, DynamicGeometryCollectionArray);
993 break;
995 AddToList(GCParticle, SleepingGeometryCollectionArray);
996 break;
997 }
998 }
999 }
1000
1002 {
1003 RemoveFromList(GCParticle, StaticGeometryCollectionArray);
1004 RemoveFromList(GCParticle, KinematicGeometryCollectionArray);
1005 RemoveFromList(GCParticle, SleepingGeometryCollectionArray);
1006 RemoveFromList(GCParticle, DynamicGeometryCollectionArray);
1007 }
1008
1009 const auto& GetClusteredParticles() const { return *ClusteredParticles; }
1010 auto& GetClusteredParticles() { return *ClusteredParticles; }
1011
1012 auto& GetUniqueIndices() { return UniqueIndices; }
1013
1014 // Check that the particles in each of the particle lists have their ListMask sett appropriately
1016
1017 // Check that no particles are in multiple lists that contribute to a single view
1019
1020private:
1021
1022 //
1023 // List Tracking System:
1024 // every particle stores the set of SOAs/ParticleMapArrays/ParticleArrays
1025 // that the particle is in. This information is used to check for invalid
1026 // combinations (some list memberships are mutually exclusive) and to
1027 // reduce the cost of checking whether a particle is in a particular list.
1028 //
1029
1030 // Initialize the list mask for all particle containers and lists
1031 CHAOS_API void SetContainerListMasks();
1032
1033 // Add a particle to the specified SOA/List and update its ListMask
1034 template<typename TListType, typename TParticleHandleType>
1035 void AddToList(TParticleHandleType* Particle, TListType& List)
1036 {
1037 //if (!Particle->IsInAnyList(List.GetContainerListMask()))
1038 {
1039 Particle->AddToLists(List.GetContainerListMask());
1040 List.Insert(Particle);
1041 }
1042 }
1043
1044 // Add a set of particles to the specified SOA/List and update their ListMasks
1045 template<typename TListType, typename TParticleHandleType>
1046 void AddToList(const TArray<TParticleHandleType*> Particles, TListType& List)
1047 {
1048 check(List.GetContainerListMask() != EGeometryParticleListMask::None);
1049
1050 for (TParticleHandleType* Particle : Particles)
1051 {
1052 Particle->AddToLists(List.GetContainerListMask());
1053 }
1054 List.Insert(Particles);
1055 }
1056
1057 // Remove a particle from the specified SOA/List and update its ListMask
1058 template<typename TListType, typename TParticleHandleType>
1059 void RemoveFromList(TParticleHandleType* Particle, TListType& List)
1060 {
1061 check(List.GetContainerListMask() != EGeometryParticleListMask::None);
1062
1063 //if (Particle->IsInAnyList(List.GetContainerListMask()))
1064 {
1065 Particle->RemoveFromLists(List.GetContainerListMask());
1066 List.Remove(Particle);
1067 }
1068 }
1069
1070 // Check that the particles in an SOA have the appropriate bit set in their ListMask
1071 template<typename TSOAType>
1072 void CheckSOAMasks(TSOAType* SOA)
1073 {
1076 for (const auto& Particle : View)
1077 {
1078 ensureAlwaysMsgf(Particle.IsInAnyList(SOA->GetContainerListMask()), TEXT("Particle %s ListMask missing expected SOA bit 0x%x"), *GetParticleDebugName(Particle), SOA->GetContainerListMask());
1079 }
1080 }
1081
1082 // Check that the particles in a List have the appropriate bit set in their ListMask
1083 template<typename TListType>
1084 void CheckListMasks(TListType& List)
1085 {
1089 for (const auto& Particle : View)
1090 {
1091 ensureAlwaysMsgf(Particle.IsInAnyList(List.GetContainerListMask()), TEXT("Particle %s ListMask missing expected List bit 0x%x"), *GetParticleDebugName(Particle), List.GetContainerListMask());
1092 }
1093 }
1094
1095 // Make sure the particle is not in a set of lists that would cause it to appear in any single view multiple times
1096 void CheckParticleViewMask(const FGeometryParticleHandle* Particle) const
1097 {
1098 // This is called after every change to a particle's SOA/List for validation.
1099 // It should be cheap when the cvar is disabled but we fully remove it in shipping anyway
1100#if !UE_BUILD_SHIPPING
1102 {
1103 CheckParticleViewMaskImpl(Particle);
1104 }
1105#endif
1106 }
1107
1108 // Make sure the particle is not in a set of lists that would cause it to appear in any single view multiple times
1109 CHAOS_API void CheckParticleViewMaskImpl(const FGeometryParticleHandle* Particle) const;
1110
1111
1112 template <typename TParticleHandleType, typename TParticles>
1113 TArray<TParticleHandleType*> CreateParticlesHelper(int32 NumParticles, const FUniqueIdx* ExistingIndices, TUniquePtr<TParticles>& Particles, const FGeometryParticleParameters& Params)
1114 {
1115 const int32 ParticlesStartIdx = Particles->Size();
1116 Particles->AddParticles(NumParticles);
1118 ReturnHandles.AddUninitialized(NumParticles);
1119
1120 const int32 HandlesStartIdx = ParticleHandles.Size();
1121 ParticleHandles.AddHandles(NumParticles);
1122
1123 for (int32 Count = 0; Count < NumParticles; ++Count)
1124 {
1125 const int32 ParticleIdx = Count + ParticlesStartIdx;
1126 const int32 HandleIdx = Count + HandlesStartIdx;
1127
1128 TUniquePtr<TParticleHandleType> NewParticleHandle = TParticleHandleType::CreateParticleHandle(MakeSerializable(Particles), ParticleIdx, HandleIdx);
1129 NewParticleHandle->SetParticleID(FParticleID{ INDEX_NONE, BiggestParticleID++ });
1130 NewParticleHandle->AddToLists(Particles->GetContainerListMask());
1132 //If unique indices are null it means there is no GT particle that already registered an ID, so create one
1133 if(ExistingIndices)
1134 {
1135 ReturnHandles[Count]->SetUniqueIdx(ExistingIndices[Count]);
1136 }
1137 else
1138 {
1139 ReturnHandles[Count]->SetUniqueIdx(UniqueIndices.GenerateUniqueIdx());
1140 }
1141 ParticleHandles.Handle(HandleIdx) = MoveTemp(NewParticleHandle);
1142 Particles->HasCollision(ParticleIdx) = true; //todo: find a better place for this
1143 }
1144
1145 return ReturnHandles;
1146 }
1147
1148 void AddToActiveArray(const TArray<FPBDRigidParticleHandle*>& Particles)
1149 {
1150 AddToList(Particles, ActiveParticlesMapArray);
1151
1152 if(bResimulating)
1153 {
1154 AddToList(Particles, ResimActiveParticlesMapArray);
1155 }
1156
1157 //dirty contains Active so make sure no duplicates
1158 for(FPBDRigidParticleHandle* Particle : Particles)
1159 {
1160 RemoveFromList(Particle, TransientDirtyMapArray);
1161 }
1162 }
1163
1164 void AddToActiveArray(FPBDRigidParticleHandle* Particle)
1165 {
1166 AddToList(Particle, ActiveParticlesMapArray);
1167
1168 if (bResimulating)
1169 {
1170 AddToList(Particle, ResimActiveParticlesMapArray);
1171 }
1172
1173 //dirty contains Active so make sure no duplicates
1174 RemoveFromList(Particle, TransientDirtyMapArray);
1175 }
1176
1177 void RemoveFromActiveArray(FPBDRigidParticleHandle* Particle, bool bStillDirty)
1178 {
1179 RemoveFromList(Particle, ActiveParticlesMapArray);
1180
1181 if (bResimulating)
1182 {
1183 RemoveFromList(Particle, ResimActiveParticlesMapArray);
1184 }
1185
1186 if(bStillDirty)
1187 {
1188 if(!MovingKinematicsMapArray.Contains(Particle))
1189 {
1190 //no longer active, but still dirty
1191 AddToList(Particle, TransientDirtyMapArray);
1192 }
1193 }
1194 else
1195 {
1196 //might have already been removed from active from a previous call
1197 //but now removing and don't want it dirty either
1198 RemoveFromList(Particle, TransientDirtyMapArray);
1199 }
1200 }
1201
1202 //should be called whenever particles are added / removed / reordered
1203 CHAOS_API void UpdateViews();
1204
1205 void InsertClusteredParticle(FPBDRigidClusteredParticleHandle* ClusteredParticle)
1206 {
1207 if (!ClusteredParticle->Disabled())
1208 {
1209 switch (ClusteredParticle->ObjectState())
1210 {
1212 ensure(false); // we should probably not be here
1213 break;
1215 AddToList(ClusteredParticle, StaticClusteredMapArray);
1216 break;
1218 AddToList(ClusteredParticle, KinematicClusteredMapArray);
1219 break;
1222 AddToList(ClusteredParticle, DynamicClusteredMapArray);
1223 break;
1224 }
1225 }
1226 }
1227
1228 void InsertClusteredParticles(const TArray<FPBDRigidClusteredParticleHandle*>& ClusteredParticleArray)
1229 {
1231 {
1232 InsertClusteredParticle(ClusteredParticle);
1233 }
1234 }
1235
1236 void RemoveClusteredParticle(FPBDRigidClusteredParticleHandle* ClusteredParticle)
1237 {
1238 RemoveFromList(ClusteredParticle, StaticClusteredMapArray);
1239 RemoveFromList(ClusteredParticle, KinematicClusteredMapArray);
1240 RemoveFromList(ClusteredParticle, DynamicClusteredMapArray);
1241 }
1242
1243 //Organized by SOA type
1244 TUniquePtr<FGeometryParticles> StaticParticles;
1245 TUniquePtr<FGeometryParticles> StaticDisabledParticles;
1246
1247 TUniquePtr<FKinematicGeometryParticles> KinematicParticles;
1248 TUniquePtr<FKinematicGeometryParticles> KinematicDisabledParticles;
1249
1250 TUniquePtr<FPBDRigidParticles> DynamicParticles;
1251 TUniquePtr<FPBDRigidParticles> DynamicKinematicParticles;
1252 TUniquePtr<FPBDRigidParticles> DynamicDisabledParticles;
1253
1254 TUniquePtr<FPBDRigidClusteredParticles> ClusteredParticles;
1255
1256 TUniquePtr<TPBDGeometryCollectionParticles<FReal, 3>> GeometryCollectionParticles;
1257
1258 //
1259 // NOTE: The member here are enumerated in EGeometryParticleListMask which must
1260 // be kept up to date with changes here. Also see SetContainerListMasks() and CheckListMasks()
1261 //
1262
1263 // Geometry collection particle state is controlled via their disabled state and assigned
1264 // EObjectStateType, and are shuffled into these corresponding arrays in UpdateGeometryCollectionViews().
1265 TParticleMapArray<FPBDGeometryCollectionParticleHandle> StaticGeometryCollectionArray;
1266 TParticleMapArray<FPBDGeometryCollectionParticleHandle> KinematicGeometryCollectionArray;
1267 TParticleMapArray<FPBDGeometryCollectionParticleHandle> SleepingGeometryCollectionArray;
1268 TParticleMapArray<FPBDGeometryCollectionParticleHandle> DynamicGeometryCollectionArray;
1269
1270 // Utility structures for maintaining an Active particles view
1271 TParticleMapArray<FPBDRigidParticleHandle> ActiveParticlesMapArray;
1272 TParticleMapArray<FPBDRigidParticleHandle> TransientDirtyMapArray;
1273
1274 // Keep track of kinematic that have their kinematic target set for this current frame
1275 TParticleMapArray<FPBDRigidParticleHandle> MovingKinematicsMapArray;
1276
1277 // Structures for maintaining a subset view during a resim (TParticleMapArray used when we need to dynamically add/remove during resim)
1278 TParticleMapArray<FPBDRigidParticleHandle> ResimActiveParticlesMapArray;
1279 TParticleMapArray<FPBDRigidParticleHandle> ResimDynamicParticles;
1280 TParticleMapArray<FPBDRigidParticleHandle> ResimDynamicKinematicParticles;
1281 TParticleArray<FGeometryParticleHandle> ResimStaticParticles;
1283 bool bResimulating = false;
1284
1285 // NonDisabled clustered particle arrays
1287 TParticleMapArray<FPBDRigidClusteredParticleHandle> KinematicClusteredMapArray;
1289
1290 // Particle Views
1291 TParticleView<FGeometryParticles> NonDisabledView; //all particles that are not disabled
1292 TParticleView<FPBDRigidParticles> NonDisabledDynamicView; //all dynamic particles that are not disabled
1293 TParticleView<FPBDRigidClusteredParticles> NonDisabledClusteredView; //all clustered particles that are not disabled
1294 TParticleView<FPBDRigidParticles> ActiveParticlesView; //all particles that are active
1295 TParticleView<FPBDRigidParticles> DirtyParticlesView; //all particles that are active + any that were put to sleep this frame
1296 TParticleView<FGeometryParticles> AllParticlesView; //all particles
1297 TParticleView<FKinematicGeometryParticles> ActiveKinematicParticlesView; //all kinematic particles that are not disabled
1298 TParticleView<FPBDRigidParticles> ActiveMovingKinematicParticlesView; //all moving kinematic particles that are not disabled
1299 TParticleView<FPBDRigidParticles> ActiveDynamicMovingKinematicParticlesView; //all moving kinematic particles that are not disabled + all dynamic particles
1300 TParticleView<FGeometryParticles> ActiveStaticParticlesView; //all static particles that are not disabled
1301 TParticleView<TPBDGeometryCollectionParticles<FReal, 3>> ActiveGeometryCollectionParticlesView; // all geom collection particles that are not disabled
1302
1303 // Auxiliary data synced with particle handles
1304 TGeometryParticleHandles<FReal, 3> ParticleHandles;
1305
1306 IParticleUniqueIndices& UniqueIndices;
1307
1308#if CHAOS_DETERMINISTIC
1310#endif
1311};
1312
1313template <typename T, int d>
1314using TPBDRigidsSOAs UE_DEPRECATED(4.27, "Deprecated. this class is to be deleted, use FPBDRigidsSOAs instead") = FPBDRigidsSOAs;
1315
1316}
#define ensureAlwaysMsgf(InExpression, InFormat,...)
Definition AssertionMacros.h:467
#define check(expr)
Definition AssertionMacros.h:314
#define ensure( InExpression)
Definition AssertionMacros.h:464
#define CVD_TRACE_PARTICLE_DESTROYED(DestroyedParticleHandle)
Definition ChaosVDTraceMacros.h:274
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
FPlatformTypes::int8 int8
An 8-bit signed integer.
Definition Platform.h:1121
#define TEXT(x)
Definition Platform.h:1272
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 LLM_SCOPE_BYNAME(...)
Definition LowLevelMemTracker.h:1098
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ChaosArchive.h:364
Definition ChaosArchive.h:167
Definition PBDRigidsSOAs.h:269
const TParticleView< FGeometryParticles > & GetActiveStaticParticlesView() const
Definition PBDRigidsSOAs.h:947
TParticleView< FPBDRigidParticles > & GetActiveParticlesView()
Definition PBDRigidsSOAs.h:931
const TArray< FPBDGeometryCollectionParticleHandle * > & GetDynamicGeometryCollectionArray() const
Definition PBDRigidsSOAs.h:973
void RemoveGeometryCollectionParticle(TPBDGeometryCollectionParticleHandle< FReal, 3 > *GCParticle)
Definition PBDRigidsSOAs.h:1001
void RebuildViews()
Definition PBDRigidsSOAs.h:689
void ActivateParticles(const TArray< FGeometryParticleHandle * > &Particles)
Definition PBDRigidsSOAs.h:625
void ActivateParticle(FGeometryParticleHandle *Particle, const bool DeferUpdateViews=false)
Definition PBDRigidsSOAs.h:590
void UpdateDirtyViews()
Definition PBDRigidsSOAs.h:329
TParticleView< FPBDRigidParticles > & GetActiveDynamicMovingKinematicParticlesView()
Definition PBDRigidsSOAs.h:951
FPBDRigidsSOAs(const FPBDRigidsSOAs &)=delete
void DestroyParticle(FGeometryParticleHandle *Particle)
Definition PBDRigidsSOAs.h:440
TParticleView< FPBDRigidParticles > & GetActiveMovingKinematicParticlesView()
Definition PBDRigidsSOAs.h:945
const TPBDGeometryCollectionParticles< FReal, 3 > & GetGeometryCollectionParticles() const
Definition PBDRigidsSOAs.h:969
FPBDRigidsSOAs(FPBDRigidsSOAs &&Other)=delete
const TParticleView< FGeometryParticles > & GetNonDisabledView() const
Definition PBDRigidsSOAs.h:924
CHAOS_API void CheckListMasks()
Definition PBDRigidsSOAs.cpp:195
const TArray< FPBDGeometryCollectionParticleHandle * > & GetSleepingGeometryCollectionArray() const
Definition PBDRigidsSOAs.h:972
TArray< FGeometryParticleHandle * > CreateStaticParticles(int32 NumParticles, const FUniqueIdx *ExistingIndices=nullptr, const FGeometryParticleParameters &Params=FGeometryParticleParameters())
Definition PBDRigidsSOAs.h:335
FPBDRigidsSOAs(IParticleUniqueIndices &InUniqueIndices)
Definition PBDRigidsSOAs.h:271
const TParticleView< FPBDRigidParticles > & GetDirtyParticlesView() const
Definition PBDRigidsSOAs.h:935
TArray< FKinematicGeometryParticleHandle * > CreateKinematicParticles(int32 NumParticles, const FUniqueIdx *ExistingIndices=nullptr, const FKinematicGeometryParticleParameters &Params=FKinematicGeometryParticleParameters())
Definition PBDRigidsSOAs.h:343
FPBDRigidParticles & GetDynamicParticles()
Definition PBDRigidsSOAs.h:957
FGeometryParticles & GetNonDisabledStaticParticles()
Definition PBDRigidsSOAs.h:967
void DeactivateParticle(FGeometryParticleHandle *Particle, const bool DeferUpdateViews=false)
Definition PBDRigidsSOAs.h:641
auto & GetClusteredParticles()
Definition PBDRigidsSOAs.h:1010
auto & GetUniqueIndices()
Definition PBDRigidsSOAs.h:1012
void SetClusteredParticleSOA(FPBDRigidClusteredParticleHandle *ClusteredParticle)
Definition PBDRigidsSOAs.h:782
FPBDRigidParticles & GetDynamicKinematicParticles()
Definition PBDRigidsSOAs.h:960
void InsertGeometryCollectionParticle(TPBDGeometryCollectionParticleHandle< FReal, 3 > *GCParticle)
Definition PBDRigidsSOAs.h:975
FPBDRigidParticles & GetDynamicDisabledParticles()
Definition PBDRigidsSOAs.h:964
void ClearTransientDirty()
Definition PBDRigidsSOAs.h:414
const TGeometryParticleHandles< FReal, 3 > & GetParticleHandles() const
Definition PBDRigidsSOAs.h:953
void DisableParticle(FGeometryParticleHandle *Particle)
Definition PBDRigidsSOAs.h:496
TArray< FPBDRigidClusteredParticleHandle * > CreateClusteredParticles(int32 NumParticles, const FUniqueIdx *ExistingIndices=nullptr, const FPBDRigidParticleParameters &Params=FPBDRigidParticleParameters())
Definition PBDRigidsSOAs.h:393
void Reset()
Definition PBDRigidsSOAs.h:307
const TParticleView< FPBDRigidClusteredParticles > & GetNonDisabledClusteredView() const
Definition PBDRigidsSOAs.h:928
void Serialize(FChaosArchive &Ar)
Definition PBDRigidsSOAs.h:857
const TParticleView< FPBDRigidParticles > & GetActiveMovingKinematicParticlesView() const
Definition PBDRigidsSOAs.h:944
void MarkMovingKinematic(FKinematicGeometryParticleHandle *Particle)
Definition PBDRigidsSOAs.h:817
const FPBDRigidParticles & GetDynamicDisabledParticles() const
Definition PBDRigidsSOAs.h:963
const FPBDRigidParticles & GetDynamicKinematicParticles() const
Definition PBDRigidsSOAs.h:959
const TParticleView< FPBDRigidParticles > & GetActiveParticlesView() const
Definition PBDRigidsSOAs.h:930
const auto & GetClusteredParticles() const
Definition PBDRigidsSOAs.h:1009
void ShrinkArrays(const float MaxSlackFraction, const int32 MinSlack)
Definition PBDRigidsSOAs.h:312
const FPBDRigidParticles & GetDynamicParticles() const
Definition PBDRigidsSOAs.h:956
const TParticleView< FGeometryParticles > & GetAllParticlesView() const
Definition PBDRigidsSOAs.h:938
void DeactivateParticles(const TArray< FGeometryParticleHandle * > &Particles)
Definition PBDRigidsSOAs.h:677
TPBDGeometryCollectionParticles< FReal, 3 > & GetGeometryCollectionParticles()
Definition PBDRigidsSOAs.h:970
const TParticleView< FPBDRigidParticles > & GetActiveDynamicMovingKinematicParticlesView() const
Definition PBDRigidsSOAs.h:950
void EnableParticle(FGeometryParticleHandle *Particle)
Definition PBDRigidsSOAs.h:543
void MarkTransientDirtyParticle(FGeometryParticleHandle *Particle, const bool bUpdateViews=true)
Definition PBDRigidsSOAs.h:421
void SetDynamicParticleSOA(FPBDRigidParticleHandle *Particle)
Definition PBDRigidsSOAs.h:694
void UpdateAllMovingKinematic(const bool bUpdateViews=true)
Definition PBDRigidsSOAs.h:829
const TParticleView< FKinematicGeometryParticles > & GetActiveKinematicParticlesView() const
Definition PBDRigidsSOAs.h:941
~FPBDRigidsSOAs()
Definition PBDRigidsSOAs.h:300
TParticleView< FPBDRigidParticles > & GetDirtyParticlesView()
Definition PBDRigidsSOAs.h:936
const FGeometryParticles & GetNonDisabledStaticParticles() const
Definition PBDRigidsSOAs.h:966
TParticleView< FGeometryParticles > & GetActiveStaticParticlesView()
Definition PBDRigidsSOAs.h:948
TArray< FPBDRigidParticleHandle * > CreateDynamicParticles(int32 NumParticles, const FUniqueIdx *ExistingIndices=nullptr, const FPBDRigidParticleParameters &Params=FPBDRigidParticleParameters())
Definition PBDRigidsSOAs.h:351
CHAOS_API void CheckViewMasks()
Definition PBDRigidsSOAs.cpp:224
TArray< TPBDGeometryCollectionParticleHandle< FReal, 3 > * > CreateGeometryCollectionParticles(int32 NumParticles, const FUniqueIdx *ExistingIndices=nullptr, const FPBDRigidParticleParameters &Params=FPBDRigidParticleParameters())
Definition PBDRigidsSOAs.h:364
const TParticleView< FPBDRigidParticles > & GetNonDisabledDynamicView() const
Definition PBDRigidsSOAs.h:926
const TArray< FPBDRigidParticleHandle * > & GetActiveParticlesArray() const
Definition PBDRigidsSOAs.h:933
TGeometryParticleHandles< FReal, 3 > & GetParticleHandles()
Definition PBDRigidsSOAs.h:954
TParticleView< FKinematicGeometryParticles > & GetActiveKinematicParticlesView()
Definition PBDRigidsSOAs.h:942
Definition PBDRigidsSOAs.h:37
void ReleaseIdx(FUniqueIdx Unique) override
Definition PBDRigidsSOAs.h:72
~FParticleUniqueIndicesMultithreaded()
Definition PBDRigidsSOAs.h:81
FUniqueIdx GenerateUniqueIdx() override
Definition PBDRigidsSOAs.h:46
FParticleUniqueIndicesMultithreaded()
Definition PBDRigidsSOAs.h:39
Definition PBDRigidsSOAs.h:29
virtual FUniqueIdx GenerateUniqueIdx()=0
virtual void ReleaseIdx(FUniqueIdx Unique)=0
virtual ~IParticleUniqueIndices()=default
uint32 Size() const
Definition ArrayCollection.h:66
Definition ParticleHandle.h:436
EObjectStateType ObjectState() const
Definition ParticleHandle.h:1716
EParticleType Type
Definition ParticleHandle.h:413
const TPBDRigidParticleHandleImp< T, d, bPersistent > * CastToRigidParticle() const
Definition ParticleHandle.h:1697
const TKinematicGeometryParticleHandleImp< T, d, bPersistent > * CastToKinematicParticle() const
Definition ParticleHandle.h:1694
void MoveToSOA(TGeometryParticles< T, d > &ToSOA)
Definition ParticleHandle.h:786
const TPBDGeometryCollectionParticleHandleImp< T, d, bPersistent > * CastToGeometryCollection() const
Definition ParticleHandle.h:1709
const TPBDRigidClusteredParticleHandleImp< T, d, bPersistent > * CastToClustered() const
Definition ParticleHandle.h:1703
Definition ParticleHandle.h:2663
const TUniquePtr< TGeometryParticleHandle< T, d > > & Handle(int32 Idx) const
Definition ParticleHandle.h:2704
void AddHandles(int32 NumHandles)
Definition ParticleHandle.h:2670
void DestroyHandleSwap(TGeometryParticleHandle< T, d > *Handle)
Definition ParticleHandle.h:2680
void Serialize(FChaosArchive &Ar)
Definition ParticleHandle.h:2698
Definition GeometryParticles.h:152
Definition ParticleHandle.h:907
Definition ParticleHandle.h:1641
Definition PBDGeometryCollectionParticles.h:11
Definition ParticleHandle.h:987
EObjectStateType ObjectState() const
Definition ParticleHandle.h:1260
bool Disabled() const
Definition ParticleHandle.h:1069
Definition PBDRigidParticles.h:22
Definition PBDRigidsSOAs.h:230
void Reset()
Definition PBDRigidsSOAs.h:237
void Insert(TParticleType *Particle)
Definition PBDRigidsSOAs.h:247
void SetContainerListMask(const EGeometryParticleListMask InMask)
Definition PBDRigidsSOAs.h:260
void Remove(TParticleType *Particle)
Definition PBDRigidsSOAs.h:252
TArray< TParticleType * > & GetArray()
Definition PBDRigidsSOAs.h:258
bool Contains(const TParticleType *Particle) const
Definition PBDRigidsSOAs.h:242
EGeometryParticleListMask GetContainerListMask() const
Definition PBDRigidsSOAs.h:261
TParticleArray()
Definition PBDRigidsSOAs.h:232
const TArray< TParticleType * > & GetArray() const
Definition PBDRigidsSOAs.h:257
Definition PBDRigidsSOAs.h:129
TParticleMapArray()
Definition PBDRigidsSOAs.h:131
bool Contains(const TParticleType *Particle) const
Definition PBDRigidsSOAs.h:142
void Remove(TParticleType *Particle)
Definition PBDRigidsSOAs.h:184
EGeometryParticleListMask GetContainerListMask() const
Definition PBDRigidsSOAs.h:215
void Serialize(FChaosArchive &Ar)
Definition PBDRigidsSOAs.h:199
void SetContainerListMask(const EGeometryParticleListMask InMask)
Definition PBDRigidsSOAs.h:214
void Insert(TParticleType *Particle)
Definition PBDRigidsSOAs.h:175
const TArray< TParticleType * > & GetArray() const
Definition PBDRigidsSOAs.h:211
void Insert(const TArray< TParticle1 * > &ParticlesToInsert)
Definition PBDRigidsSOAs.h:148
void Reset()
Definition PBDRigidsSOAs.h:136
TArray< TParticleType * > & GetArray()
Definition PBDRigidsSOAs.h:212
Definition ParticleIterator.h:639
FORCEINLINE TArray< TSleepData< T, d > > & GetSleepData()
Definition RigidParticles.h:257
FORCEINLINE FRWLock & GetSleepDataLock()
Definition RigidParticles.h:274
virtual CORE_API void UsingCustomVersion(const struct FGuid &Guid)
Definition Archive.cpp:590
UE_FORCEINLINE_HINT bool IsLoading() const
Definition Archive.h:236
CORE_API int32 CustomVer(const struct FGuid &Key) const
Definition Archive.cpp:602
Definition NameTypes.h:617
Definition Array.h:670
UE_FORCEINLINE_HINT SizeType AddUninitialized()
Definition Array.h:1664
SizeType Remove(const ElementType &Item)
Definition Array.h:3091
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Reset(SizeType NewSize=0)
Definition Array.h:2246
UE_FORCEINLINE_HINT void RemoveAtSwap(SizeType Index, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2185
bool Contains(const ComparisonType &Item) const
Definition Array.h:1518
UE_FORCEINLINE_HINT SizeType Emplace(ArgsType &&... Args)
Definition Array.h:2561
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
SizeType AddZeroed()
Definition Array.h:2755
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
Definition LockFreeList.h:910
Definition UnrealString.h.inl:34
Definition UniquePtr.h:107
UE_REWRITE void WriteLock()
Definition CriticalSection.h:21
UE_REWRITE void WriteUnlock()
Definition CriticalSection.h:26
bool bChaosSolverCheckParticleViews
Definition PBDRigidsEvolutionGBF.cpp:233
bool bRemoveParticleFromMovingKinematicsOnDisable
Definition PBDRigidsSolver.cpp:422
Definition SkeletalMeshComponent.h:307
TVector< FRealSingle, 3 > FVec3f
Definition Core.h:27
TPBDRigidParticleHandle< FReal, 3 > FPBDRigidParticleHandle
Definition ParticleHandleFwd.h:60
TEnableIf< T::AlwaysSerializable, TArray< TSerializablePtr< T > > >::Type & AsAlwaysSerializableArray(TArray< T * > &Ptrs)
Definition Serializable.h:104
TConstParticleView< TSOA > MakeConstParticleView(TArray< TSOAView< TSOA > > &&SOAViews)
Definition ParticleIterator.h:681
const FString & GetParticleDebugName(const TParticleType &Particle)
Definition PBDRigidsSOAs.h:18
TSerializablePtr< T > MakeSerializable(const TUniquePtr< T > &Unique)
Definition Serializable.h:60
EObjectStateType
Definition ObjectState.h:10
TGeometryParticleHandle< FReal, 3 > FGeometryParticleHandle
Definition ParticleHandleFwd.h:24
TPBDRigidClusteredParticleHandle< FReal, 3 > FPBDRigidClusteredParticleHandle
Definition ParticleHandleFwd.h:75
EGeometryParticleListMask
Definition GeometryParticlesfwd.h:115
@ List
Definition ITypedTableView.h:38
FAutoConsoleVariableRef CVars[]
Definition MassProcessingPhaseManager.cpp:29
U16 Index
Definition radfft.cpp:71
Definition ParticleHandle.h:47
Definition ParticleHandle.h:57
Definition ParticleHandle.h:67
Definition GeometryParticlesfwd.h:87
Definition RigidParticles.h:30
TGeometryParticleHandle< T, d > * Particle
Definition RigidParticles.h:42
CORE_API static const FGuid GUID
Definition ExternalPhysicsCustomObjectVersion.h:144
@ AddDynamicKinematicSOA
Definition ExternalPhysicsCustomObjectVersion.h:64