// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #pragma once #include "Misc/Build.h" #if INCLUDE_CHAOS && !(UE_BUILD_SHIPPING || UE_BUILD_TEST) #include "Containers/StaticBitArray.h" #include "Chaos/ArrayCollectionArray.h" #include "Chaos/ImplicitObject.h" #include "Chaos/Matrix.h" #include "Chaos/UniformGrid.h" #include "Chaos/PBDRigidClustering.h" #include "Chaos/Framework/BufferedData.h" class FChaosSolversModule; namespace Chaos { class FPBDRigidsSolver; } template class TManagedArray; /** Enumeration of the synchronizable data. */ enum class EGeometryCollectionParticlesData : uint8 { X, R, Geometry, GeometryType, GeometryIsConvex, GeometryHasBoundingBox, GeometryBoxMin, GeometryBoxMax, GeometrySphereCenter, GeometrySphereRadius, GeometryLevelSetGrid, V, W, F, Torque, I, InvI, M, InvM, CollisionParticlesSize, Disabled, Sleeping, Island, P, Q, PreV, PreW, ConnectivityEdges, ChildToParentMap, Count }; /** Object holding selected particles data for a specific range of rigid body ids. Use SetDataSyncFlag, SetAllDataSyncFlag, or RequestSyncedData to have the required data made available at the next tick. Each time Sync is called, the particles' data is copied and the sync flags cleared. Use HasSyncedData or RequestSyncedData to check which data is available at any one time. */ template class TGeometryCollectionParticlesData { public: /** Constructor. */ TGeometryCollectionParticlesData(); /** Set this data type to copy at the next sync. */ void SetDataSyncFlag(EGeometryCollectionParticlesData Data) const { BufferedData.GetGameDataForRead().SetDataSyncFlag(Data); } /** Set all data type to copy at the next sync. */ void SetAllDataSyncFlag() const { BufferedData.GetGameDataForRead().SetAllDataSyncFlag(); } /** Return whether the specified type of data has been copied during the last sync. */ bool HasSyncedData(EGeometryCollectionParticlesData Data) const { return BufferedData.GetGameDataForRead().HasSyncedData(Data); } /** Shorthand for both setting the flag and checking the data has already been synced. */ bool RequestSyncedData(EGeometryCollectionParticlesData Data) const { SetDataSyncFlag(Data); return HasSyncedData(Data); } /** Copy the data of the specified set of particles/rigid body ids to this object. */ void Sync(const Chaos::FPBDRigidsSolver* Solver, const TManagedArray& RigidBodyIds); const Chaos::TVector & GetX (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::X )); return BufferedData.GetGameDataForRead().X [Index]; } const Chaos::TRotation & GetR (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::R )); return BufferedData.GetGameDataForRead().R [Index]; } const Chaos::TImplicitObject* const& GetGeometry (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::Geometry )); return BufferedData.GetGameDataForRead().Geometry [Index]; } const Chaos::ImplicitObjectType & GetGeometryType (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometryType )); return BufferedData.GetGameDataForRead().GeometryType [Index]; } const bool & IsGeometryConvex (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometryIsConvex )); return BufferedData.GetGameDataForRead().GeometryIsConvex [Index]; } const bool & HasGeometryBoundingBoxm (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometryHasBoundingBox)); return BufferedData.GetGameDataForRead().GeometryHasBoundingBox[Index]; } const Chaos::TVector & GetGeometryBoxMin (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometryBoxMin )); return BufferedData.GetGameDataForRead().GeometryBoxMin [Index]; } const Chaos::TVector & GetGeometryBoxMax (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometryBoxMax )); return BufferedData.GetGameDataForRead().GeometryBoxMax [Index]; } const Chaos::TVector & GetGeometrySphereCenter (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometrySphereCenter )); return BufferedData.GetGameDataForRead().GeometrySphereCenter [Index]; } const T & GetGeometrySphereRadius (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometrySphereRadius )); return BufferedData.GetGameDataForRead().GeometrySphereRadius [Index]; } const Chaos::TUniformGrid & GetGeometryLevelSetGrid (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::GeometryLevelSetGrid )); return BufferedData.GetGameDataForRead().GeometryLevelSetGrid [Index]; } const Chaos::TVector & GetV (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::V )); return BufferedData.GetGameDataForRead().V [Index]; } const Chaos::TVector & GetW (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::W )); return BufferedData.GetGameDataForRead().W [Index]; } const Chaos::TVector & GetF (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::F )); return BufferedData.GetGameDataForRead().F [Index]; } const Chaos::TVector & GetTorque (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::Torque )); return BufferedData.GetGameDataForRead().Torque [Index]; } const Chaos::PMatrix & GetI (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::I )); return BufferedData.GetGameDataForRead().I [Index]; } const Chaos::PMatrix & GetInvI (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::InvI )); return BufferedData.GetGameDataForRead().InvI [Index]; } const T & GetM (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::M )); return BufferedData.GetGameDataForRead().M [Index]; } const T & GetInvM (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::InvM )); return BufferedData.GetGameDataForRead().InvM [Index]; } const int32 & GetCollisionParticlesSize(int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::CollisionParticlesSize)); return BufferedData.GetGameDataForRead().CollisionParticlesSize[Index]; } const bool & IsDisabled (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::Disabled )); return BufferedData.GetGameDataForRead().Disabled [Index]; } const bool & IsSleeping (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::Sleeping )); return BufferedData.GetGameDataForRead().Sleeping [Index]; } const int32 & GetIsland (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::Island )); return BufferedData.GetGameDataForRead().Island [Index]; } const Chaos::TVector & GetP (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::P )); return BufferedData.GetGameDataForRead().P [Index]; } const Chaos::TRotation & GetQ (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::Q )); return BufferedData.GetGameDataForRead().Q [Index]; } const Chaos::TVector & GetPreV (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::PreV )); return BufferedData.GetGameDataForRead().PreV [Index]; } const Chaos::TVector & GetPreW (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::PreW )); return BufferedData.GetGameDataForRead().PreW [Index]; } const TArray>& GetConnectivityEdges (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::ConnectivityEdges )); return BufferedData.GetGameDataForRead().ConnectivityEdges [Index]; } const Chaos::TRigidTransform & GetChildToParentMap (int32 Index) const { check(HasSyncedData(EGeometryCollectionParticlesData::ChildToParentMap )); return BufferedData.GetGameDataForRead().ChildToParentMap [Index]; } /** Return a string with the entire set of value for the synced data of the specified particle. */ FString ToString(int32 Index, const TCHAR* Separator = TEXT(", ")) const { return BufferedData.GetGameDataForRead().ToString(Index, Separator); } private: /** Data bit selection type. */ typedef TStaticBitArray FDataFlags; /** Structure used to exchange data between game and physics thread. */ struct FData { mutable FDataFlags RequiredDataFlags; // Mutable in order to allow const versions of all of this object's methods outside of the Sync process. FDataFlags SyncedDataFlags; Chaos::TArrayCollectionArray > X; Chaos::TArrayCollectionArray > R; Chaos::TArrayCollectionArray*> Geometry; Chaos::TArrayCollectionArray GeometryType; Chaos::TArrayCollectionArray GeometryIsConvex; Chaos::TArrayCollectionArray GeometryHasBoundingBox; Chaos::TArrayCollectionArray > GeometryBoxMin; Chaos::TArrayCollectionArray > GeometryBoxMax; Chaos::TArrayCollectionArray > GeometrySphereCenter; Chaos::TArrayCollectionArray GeometrySphereRadius; Chaos::TArrayCollectionArray > GeometryLevelSetGrid; Chaos::TArrayCollectionArray > V; Chaos::TArrayCollectionArray > W; Chaos::TArrayCollectionArray > F; Chaos::TArrayCollectionArray > Torque; Chaos::TArrayCollectionArray > I; Chaos::TArrayCollectionArray > InvI; Chaos::TArrayCollectionArray M; Chaos::TArrayCollectionArray InvM; Chaos::TArrayCollectionArray CollisionParticlesSize; Chaos::TArrayCollectionArray Disabled; Chaos::TArrayCollectionArray Sleeping; Chaos::TArrayCollectionArray Island; Chaos::TArrayCollectionArray > P; Chaos::TArrayCollectionArray > Q; Chaos::TArrayCollectionArray > PreV; Chaos::TArrayCollectionArray > PreW; Chaos::TArrayCollectionArray>> ConnectivityEdges; Chaos::TArrayCollectionArray > ChildToParentMap; /** Set this data type to copy at the next sync. */ void SetDataSyncFlag(EGeometryCollectionParticlesData Data) const { RequiredDataFlags[uint32(Data)] = true; } /** Set all data type to copy at the next sync. */ void SetAllDataSyncFlag() const; /** Return whether the specified type of data has been copied during the last sync. */ bool HasSyncedData(EGeometryCollectionParticlesData Data) const { return SyncedDataFlags[uint32(Data)]; } /** Deallocate the array containing the specified particle information. */ void Reset(EGeometryCollectionParticlesData Data); /** Copy the specified particle information for the specified range of rigid body id. */ void Copy(EGeometryCollectionParticlesData Data, const Chaos::FPBDRigidsSolver* Solver, const TManagedArray& RigidBodyIds); /** Return a string with the entire set of value for the synced data of the specified particle. */ FString ToString(int32 Index, const TCHAR* Separator) const; }; const FChaosSolversModule* ChaosModule; Chaos::TBufferedData BufferedData; FThreadSafeCounter PhysicsSyncCount; int32 GameSyncCount; uint64 SyncFrame; }; /** Current Chaos particles syncer type. */ typedef TGeometryCollectionParticlesData FGeometryCollectionParticlesData; #endif // #if INCLUDE_CHAOS && !(UE_BUILD_SHIPPING || UE_BUILD_TEST)