2020-05-05 11:41:40 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "GeometryCollection/GeometryCollectionTestClustering.h"
# include "GeometryCollection/GeometryCollectionTestFramework.h"
# include "GeometryCollection/GeometryCollectionTestUtility.h"
# include "GeometryCollection/GeometryCollection.h"
# include "GeometryCollection/GeometryCollectionUtility.h"
# include "GeometryCollection/GeometryCollectionAlgo.h"
# include "GeometryCollection/GeometryCollectionClusteringUtility.h"
# include "GeometryCollection/TransformCollection.h"
# include "UObject/Package.h"
# include "UObject/UObjectGlobals.h"
# include "Field/FieldSystem.h"
# include "Field/FieldSystemNodes.h"
# include "GeometryCollectionProxyData.h"
# include "PhysicsProxy/PhysicsProxies.h"
# include "Chaos/ErrorReporter.h"
# include "ChaosSolversModule.h"
# include "PhysicsSolver.h"
# include "Chaos/PBDRigidClustering.h"
# include "HAL/IConsoleManager.h"
# include "HeadlessChaosTestUtility.h"
DEFINE_LOG_CATEGORY_STATIC ( GCTCL_Log , Verbose , All ) ;
// #TODO Lots of duplication in here, anyone making solver or object changes
// has to go and fix up so many callsites here and they're all pretty much
// Identical. The similar code should be pulled out
namespace GeometryCollectionTest
{
using namespace ChaosTest ;
2020-06-23 18:40:00 -04:00
2022-01-03 16:19:33 -05:00
bool ClusterMapContains ( const Chaos : : FRigidClustering : : FClusterMap & ClusterMap , const FPBDRigidParticleHandle * InKey , TArray < FPBDRigidParticleHandle * > Elements )
2020-05-05 11:41:40 -04:00
{
if ( ClusterMap . Num ( ) )
2020-06-23 18:40:00 -04:00
{
2021-02-23 19:43:30 -04:00
if ( const Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * Key = InKey - > CastToClustered ( ) )
2020-05-05 11:41:40 -04:00
{
2021-02-23 19:43:30 -04:00
if ( ClusterMap . Contains ( Key ) )
2020-05-05 11:41:40 -04:00
{
2021-02-23 19:43:30 -04:00
if ( ClusterMap [ Key ] . Num ( ) = = Elements . Num ( ) )
2020-06-23 18:40:00 -04:00
{
2021-02-23 19:43:30 -04:00
for ( FPBDRigidParticleHandle * Element : Elements )
2020-06-23 18:40:00 -04:00
{
2021-02-23 19:43:30 -04:00
if ( ! ClusterMap [ Key ] . Contains ( Element ) )
{
return false ;
}
2020-06-23 18:40:00 -04:00
}
2021-02-23 19:43:30 -04:00
return true ;
}
2020-05-05 11:41:40 -04:00
}
}
2020-06-23 18:40:00 -04:00
}
2020-05-05 11:41:40 -04:00
return false ;
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_SingleLevelNonBreaking )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
RigidBodyWrapper * Floor = TNewSimulationObject < GeometryType : : RigidFloor > : : Init ( ) - > template As < RigidBodyWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Floor ) ;
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 , 0 , 0. ) ) , FVector ( 0 , - 10 , 10 ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 , 0 , 0. ) ) , FVector ( 0 , 10 , 10 ) ) , FVector ( 1.0 ) ) ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 2 ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 3 ) ;
2021-02-03 14:57:28 -04:00
RestCollection - > Transform [ 2 ] = FTransform ( FQuat : : MakeFromEuler ( FVector ( 90.0 , 0 , 0. ) ) , FVector ( 0 , 0 , 40 ) ) ;
2020-05-05 11:41:40 -04:00
//GeometryCollectionAlgo::PrintParentHierarchy(RestCollection.Get());
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 1000.f } ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
TManagedArray < bool > & Active = Collection - > DynamicCollection - > Active ;
EXPECT_TRUE ( Active [ 0 ] ) ;
EXPECT_TRUE ( Active [ 1 ] ) ;
EXPECT_TRUE ( Active [ 2 ] ) ;
UnitTest . Advance ( ) ;
EXPECT_FALSE ( Active [ 0 ] ) ;
EXPECT_FALSE ( Active [ 1 ] ) ;
EXPECT_TRUE ( Active [ 2 ] ) ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection - > PhysObject - > GetSolverClusterHandles ( ) [ 0 ] ,
{ Collection - > PhysObject - > GetSolverParticleHandles ( ) [ 0 ] , Collection - > PhysObject - > GetSolverParticleHandles ( ) [ 1 ] } ) ) ;
2021-02-03 14:57:28 -04:00
FReal InitialZ = Collection - > RestCollection - > Transform [ 2 ] . GetTranslation ( ) . Z ;
2020-05-05 11:41:40 -04:00
for ( int Frame = 1 ; Frame < 10 ; Frame + + )
{
UnitTest . Advance ( ) ;
EXPECT_FALSE ( Active [ 0 ] ) ;
EXPECT_FALSE ( Active [ 1 ] ) ;
EXPECT_TRUE ( Active [ 2 ] ) ;
CurrentRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) ;
EXPECT_LT ( FMath : : Abs ( CurrentRigidDistance - StartingRigidDistance ) , SMALL_NUMBER ) ; // two bodies under cluster maintain distance
EXPECT_LT ( Collection - > DynamicCollection - > Transform [ 2 ] . GetTranslation ( ) . Z , InitialZ ) ; // body should be falling and decreasing in Z
}
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection - > PhysObject - > GetSolverClusterHandles ( ) [ 0 ] ,
{ Collection - > PhysObject - > GetSolverParticleHandles ( ) [ 0 ] , Collection - > PhysObject - > GetSolverParticleHandles ( ) [ 1 ] } ) ) ;
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_DeactivateClusterParticle )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
// 5 cube leaf nodes
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 20.f ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 30.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 40.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 50.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 60.f ) ) , FVector ( 1.0 ) ) ) ;
// 4 mid-level cluster parents
2021-08-26 06:58:36 -04:00
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 5 , { 4 , 3 } , true , false ) ; // just validate at end of construction
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 6 , { 5 , 2 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 7 , { 6 , 1 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
FGeometryCollectionClusteringUtility : : ValidateResults ( RestCollection . Get ( ) ) ;
//GeometryCollectionAlgo::PrintParentHierarchy(RestCollection.Get());
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 50.0 , 50.0 , 50.0 , FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 7 ] , ParticleHandles [ 0 ] } ) ) ;
TArray < bool > Conditions = { false , false } ;
TArray < bool > DisabledFlags ;
for ( int Frame = 1 ; Frame < 4 ; Frame + + )
{
UnitTest . Advance ( ) ;
if ( Frame = = 2 )
{
Clustering . DeactivateClusterParticle ( ParticleHandles [ 8 ] ) ;
}
DisabledFlags . Reset ( ) ;
for ( const auto * Handle : ParticleHandles )
{
DisabledFlags . Add ( Handle - > Disabled ( ) ) ;
}
if ( Frame = = 1 )
{
if ( DisabledFlags [ 0 ] = = true & &
DisabledFlags [ 1 ] = = true & &
DisabledFlags [ 2 ] = = true & &
DisabledFlags [ 3 ] = = true & &
DisabledFlags [ 4 ] = = true & &
DisabledFlags [ 5 ] = = true & &
DisabledFlags [ 6 ] = = true & &
DisabledFlags [ 7 ] = = true & &
DisabledFlags [ 8 ] = = false )
{
Conditions [ 0 ] = true ;
}
}
else if ( Frame = = 2 | | Frame = = 3 )
{
if ( Conditions [ 0 ] = = true )
{
if ( DisabledFlags [ 0 ] = = false & &
DisabledFlags [ 1 ] = = true & &
DisabledFlags [ 2 ] = = true & &
DisabledFlags [ 3 ] = = true & &
DisabledFlags [ 4 ] = = true & &
DisabledFlags [ 5 ] = = true & &
DisabledFlags [ 6 ] = = true & &
DisabledFlags [ 7 ] = = false & &
DisabledFlags [ 8 ] = = true )
{
Conditions [ 1 ] = true ;
EXPECT_TRUE ( ! ClusterMap . Contains ( ParticleHandles [ 8 ] ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
}
}
}
}
for ( int i = 0 ; i < Conditions . Num ( ) ; i + + )
{
EXPECT_TRUE ( Conditions [ i ] ) ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_BreakClusterParticle )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
// 5 cube leaf nodes
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 20.f ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 30.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 40.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 50.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 60.f ) ) , FVector ( 1.0 ) ) ) ;
// 4 mid-level cluster parents
2021-08-26 06:58:36 -04:00
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 5 , { 4 , 3 } , true , false ) ; // just validate at end of construction
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 6 , { 5 , 2 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 7 , { 6 , 1 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
FGeometryCollectionClusteringUtility : : ValidateResults ( RestCollection . Get ( ) ) ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 50.0 , 50.0 , 50.0 , FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 7 ] , ParticleHandles [ 0 ] } ) ) ;
TArray < bool > Conditions = { false , false } ;
TArray < bool > DisabledFlags ;
for ( int Frame = 1 ; Frame < 4 ; Frame + + )
{
UnitTest . Advance ( ) ;
if ( Frame = = 2 )
{
2021-05-31 22:11:27 -04:00
TMap < FGeometryParticleHandle * , FReal > ExternalStrains = { { ParticleHandles [ 0 ] , 50.0f } } ;
2020-05-05 11:41:40 -04:00
Clustering . BreakingModel ( & ExternalStrains ) ;
}
DisabledFlags . Reset ( ) ;
for ( const auto * Handle : ParticleHandles )
{
DisabledFlags . Add ( Handle - > Disabled ( ) ) ;
}
//UE_LOG(GCTCL_Log, Verbose, TEXT("FRAME : %d"), Frame);
//for (int32 rdx = 0; rdx < (int32)Particles.Size(); rdx++)
//{
// UE_LOG(GCTCL_Log, Verbose, TEXT("... ... ...Disabled[%d] : %d"), rdx, Particles.Disabled(rdx));
// UE_LOG(GCTCL_Log, Verbose, TEXT("... ... ... InvM[%d] : %f"), rdx, Particles.InvM(rdx));
//}
if ( Frame = = 1 )
{
if ( DisabledFlags [ 0 ] = = true & &
DisabledFlags [ 1 ] = = true & &
DisabledFlags [ 2 ] = = true & &
DisabledFlags [ 3 ] = = true & &
DisabledFlags [ 4 ] = = true & &
DisabledFlags [ 5 ] = = true & &
DisabledFlags [ 6 ] = = true & &
DisabledFlags [ 7 ] = = true & &
DisabledFlags [ 8 ] = = false )
{
Conditions [ 0 ] = true ;
}
}
else if ( Frame = = 2 | | Frame = = 3 )
{
if ( Conditions [ 0 ] = = true )
{
if ( DisabledFlags [ 0 ] = = false & &
DisabledFlags [ 1 ] = = true & &
DisabledFlags [ 2 ] = = true & &
DisabledFlags [ 3 ] = = true & &
DisabledFlags [ 4 ] = = true & &
DisabledFlags [ 5 ] = = true & &
DisabledFlags [ 6 ] = = true & &
DisabledFlags [ 7 ] = = false & &
DisabledFlags [ 8 ] = = true )
{
Conditions [ 1 ] = true ;
EXPECT_TRUE ( ! ClusterMap . Contains ( ParticleHandles [ 8 ] ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
}
}
}
}
for ( int i = 0 ; i < Conditions . Num ( ) ; i + + )
{
EXPECT_TRUE ( Conditions [ i ] ) ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_SingleLevelBreaking )
2020-05-05 11:41:40 -04:00
{
//
// Test overview:
// Create two 1cm cubes in a cluster arranged vertically and 20cm apart.
// Position the cluster above the ground.
// Wait until the cluster hits the ground.
// Ensure that the cluster breaks and that the children have the correct states from then on.
//
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
UnitTest . AddSimulationObject ( TNewSimulationObject < GeometryType : : RigidFloor > : : Init ( ) - > template As < RigidBodyWrapper > ( ) ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody ( FVector : : ZeroVector ) ;
RestCollection - > Transform [ 2 ] = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0. , 90.f , 0. ) ) , FVector ( 0 , 0 , 17 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 0.1f } ;
Params . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
Collection - > PhysObject - > SetCollisionParticlesPerObjectFraction ( 1.0 ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection - > PhysObject - > GetSolverClusterHandles ( ) [ 0 ] ,
{ Collection - > PhysObject - > GetSolverParticleHandles ( ) [ 0 ] , Collection - > PhysObject - > GetSolverParticleHandles ( ) [ 1 ] } ) ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
// Particles array contains the following:
// 0: Box1 (top)
// 1: Box2 (bottom)
2020-08-11 01:36:57 -04:00
int32 BrokenFrame = INDEX_NONE ;
2020-05-05 11:41:40 -04:00
// 2: Box1+Box2 Cluster
for ( int Frame = 1 ; Frame < 20 ; Frame + + )
{
UnitTest . Advance ( ) ;
CurrentRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) ;
2020-08-11 01:36:57 -04:00
if ( ( BrokenFrame = = INDEX_NONE ) & & ! ParticleHandles [ 2 ] - > Disabled ( ) )
2020-05-05 11:41:40 -04:00
{
// The two boxes are dropping to the ground as a cluster
EXPECT_TRUE ( ParticleHandles [ 0 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 1 ] - > Disabled ( ) ) ;
2020-08-11 01:36:57 -04:00
// The boxes are still separated by StartingRigidDistance
2020-05-05 11:41:40 -04:00
EXPECT_LT ( FMath : : Abs ( CurrentRigidDistance - StartingRigidDistance ) , 1e-4 ) ;
}
2020-08-11 01:36:57 -04:00
if ( ( BrokenFrame = = INDEX_NONE ) & & ParticleHandles [ 2 ] - > Disabled ( ) )
2020-05-05 11:41:40 -04:00
{
// The cluster has just hit the ground and should have broken.
2020-08-11 01:36:57 -04:00
EXPECT_FALSE ( ParticleHandles [ 0 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 1 ] - > Disabled ( ) ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 0 ) ;
BrokenFrame = Frame ;
}
2020-05-05 11:41:40 -04:00
2020-09-23 09:19:26 -04:00
if ( ( BrokenFrame ! = INDEX_NONE ) & & ( Frame > BrokenFrame + 1 ) ) // +1 so that the boxes have a bit of time to move away from each other
2020-05-05 11:41:40 -04:00
{
// The boxes are now moving independently - the bottom one is on the ground and should be stopped.
// The top one is still falling, so they should be closer together
2020-08-11 01:36:57 -04:00
EXPECT_GT ( FMath : : Abs ( CurrentRigidDistance - StartingRigidDistance ) , 1e-4 ) ;
2020-05-05 11:41:40 -04:00
}
}
2020-08-11 01:36:57 -04:00
// Make sure it actually broke
EXPECT_FALSE ( ParticleHandles [ 0 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 1 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 2 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( BrokenFrame ! = INDEX_NONE ) ;
2020-05-05 11:41:40 -04:00
EXPECT_GT ( FMath : : Abs ( CurrentRigidDistance - StartingRigidDistance ) , 1e-4 ) ;
}
2021-10-21 13:21:05 -04:00
// Wrap two boxes in a cluster (as a sphere), and then wrap that cluster in another cluster (as a sphere).
// Drop the cluster onto the ground. The outer cluster will break, activating the inner cluster.
// Then the inner cluster will break, activating the boxes.
// Note: the inner cluster has a damage threshold of 0, so it breaks even though it is resting on
// the ground with no velocity after the outer cluster breaks.
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_NestedCluster )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
RigidBodyWrapper * Floor = TNewSimulationObject < GeometryType : : RigidFloor > : : Init ( ) - > template As < RigidBodyWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Floor ) ;
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 , 0 , 0. ) ) , FVector ( 0 , - 10 , 10 ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 , 0 , 0. ) ) , FVector ( 0 , 10 , 10 ) ) , FVector ( 1.0 ) ) ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 2 ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 3 ) ;
RestCollection - > Transform [ 2 ] = FTransform ( FQuat : : MakeFromEuler ( FVector ( 90.f , 0 , 0. ) ) , FVector ( 0 , 0 , 40 ) ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 3 , { 2 } , true ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 4 ) ;
RestCollection - > Transform [ 3 ] = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f , 0 , 0. ) ) , FVector ( 0 , 0 , 10 ) ) ;
//GeometryCollectionAlgo::PrintParentHierarchy(RestCollection.Get());
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
2021-10-21 13:21:05 -04:00
Params . DamageThreshold = { 0.1f , 0.0f } ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2021-10-21 13:21:05 -04:00
// Particle Handles array contains
// [0]: GeometryCollection Sphere0 at 0,10,60
// [1]: GeometryCollection Sphere1 at 0,10,40
// [2]: GeometryCollection Cluster0 of Sphere0 and Sphere1 at 0,10,50 (root rotated 90deg about X)
// [3]: GeometryCollection Cluster1 of Cluster0 at 0,10,50
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 2 ] , { ParticleHandles [ 0 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 3 ] , { ParticleHandles [ 2 ] } ) ) ;
TArray < bool > Conditions = { false , false , false } ;
for ( int Frame = 1 ; Frame < 100 ; Frame + + )
{
UnitTest . Advance ( ) ;
CurrentRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) ;
if ( Conditions [ 0 ] = = false )
{
if (
ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = false )
{
2021-10-21 13:21:05 -04:00
// Only the outer Cluster1 is active.
// This is the initial condition
2020-05-05 11:41:40 -04:00
Conditions [ 0 ] = true ;
}
}
else if ( Conditions [ 0 ] = = true & & Conditions [ 1 ] = = false )
{
if (
ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = false & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true )
{
2021-10-21 13:21:05 -04:00
// Cluster1 is now disabled, and Cluster0 was activated.
// This happens when Cluster1 collides with the floor
2020-05-05 11:41:40 -04:00
Conditions [ 1 ] = true ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 2 ] , { ParticleHandles [ 0 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ! ClusterMap . Contains ( ParticleHandles [ 3 ] ) ) ;
}
}
else if ( Conditions [ 1 ] = = true & & Conditions [ 2 ] = = false )
{
if (
ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
ParticleHandles [ 1 ] - > Disabled ( ) = = false & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true )
{
2021-10-21 13:21:05 -04:00
// Cluster0 is now disabled because it had a damage threshold of 0
// and the boxes should now be active.
2020-05-05 11:41:40 -04:00
Conditions [ 2 ] = true ;
EXPECT_EQ ( ClusterMap . Num ( ) , 0 ) ;
}
}
}
for ( int i = 0 ; i < Conditions . Num ( ) ; i + + )
{
EXPECT_TRUE ( Conditions [ i ] ) ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_NestedCluster_NonIdentityMassToLocal )
2020-05-05 11:41:40 -04:00
{
// Advance and release each cluster, everything is kinematic, so the output transforms should never change.
// This tests the transforms in BufferPhysicsResults, validating that MassToLocal, ChildToParent, and X,P
// will properly map back into the GeometryCollections animation transform hierarchy.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody_TwoParents_TwoBodiesB ( FVector ( 0 , 0 , 20 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
Params . ClusterGroupIndex = 0 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection1 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryDynamicCollection > DynamicCollection1 = Collection1 - > DynamicCollection ;
2022-05-11 12:14:04 -04:00
DynamicCollection1 - > ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
DynamicCollection1 - > ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 0 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection1 ) ;
UnitTest . Initialize ( ) ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
TArray < FTransform > Collection1_InitialTM ; GeometryCollectionAlgo : : GlobalMatrices ( Collection1 - > RestCollection - > Transform , Collection1 - > RestCollection - > Parent , Collection1_InitialTM ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & Collection1Handles = Collection1 - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
const auto & SovlerParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 3 ] , { Collection1Handles [ 2 ] } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 3 ] , { Collection1Handles [ 2 ] } ) ) ;
TArray < FTransform > Collection1_PreReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PreReleaseTM ) ;
for ( int Idx = 0 ; Idx < Collection1_PreReleaseTM . Num ( ) ; Idx + + ) {
EXPECT_TRUE ( ( Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) - Collection1_InitialTM [ Idx ] . GetTranslation ( ) ) . Size ( ) < KINDA_SMALL_NUMBER ) ;
}
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . DeactivateClusterParticle ( { Collection1Handles [ 3 ] } ) ;
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
TArray < FTransform > Collection1_PostReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PostReleaseTM ) ;
for ( int Idx = 0 ; Idx < Collection1_PostReleaseTM . Num ( ) ; Idx + + ) {
EXPECT_TRUE ( ( Collection1_PostReleaseTM [ Idx ] . GetTranslation ( ) - Collection1_InitialTM [ Idx ] . GetTranslation ( ) ) . Size ( ) < KINDA_SMALL_NUMBER ) ;
}
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . DeactivateClusterParticle ( { Collection1Handles [ 2 ] } ) ;
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 0 ) ;
TArray < FTransform > Collection1_PostRelease2TM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PostRelease2TM ) ;
for ( int Idx = 0 ; Idx < Collection1_PostRelease2TM . Num ( ) ; Idx + + ) {
EXPECT_TRUE ( ( Collection1_PostRelease2TM [ Idx ] . GetTranslation ( ) - Collection1_InitialTM [ Idx ] . GetTranslation ( ) ) . Size ( ) < KINDA_SMALL_NUMBER ) ;
}
}
2021-08-26 07:01:50 -04:00
GTEST_TEST ( AllTraits , DISASBLED_GeometryCollection_RigidBodies_ClusterTest_NestedCluster_MultiStrain )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
RigidBodyWrapper * Floor = TNewSimulationObject < GeometryType : : RigidFloor > : : Init ( ) - > template As < RigidBodyWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Floor ) ;
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 20.f ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 30.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 40.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 50.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 60.f ) ) , FVector ( 1.0 ) ) ) ;
2021-08-26 06:58:36 -04:00
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 4 , { 2 , 3 } , true , true ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 2 , { 1 , 0 } , true , true ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 1 , { 3 , 0 } , true , true ) ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
2021-08-26 07:01:50 -04:00
Params . DamageThreshold = { 30.0 , 30.0 , 30 , FLT_MAX } ;
2021-08-26 06:58:36 -04:00
// basically a stand-in for a 'component'
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
TArray < bool > Conditions = { false , false , false , false } ;
UnitTest . Advance ( ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 4 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 7 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 8 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 3 ] , ParticleHandles [ 0 ] } ) ) ;
2020-05-05 11:41:40 -04:00
for ( int Frame = 1 ; Frame < 40 ; Frame + + )
{
UnitTest . Advance ( ) ;
CurrentRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) ;
if ( Conditions [ 0 ] = = false )
{
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 5 ] - > Disabled ( ) = = false & & // root
2020-05-05 11:41:40 -04:00
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
2020-05-05 11:41:40 -04:00
{
Conditions [ 0 ] = true ;
}
}
2021-08-26 06:58:36 -04:00
// Root cluster broken, check for activated children
2020-05-05 11:41:40 -04:00
else if ( Conditions [ 0 ] = = true & & Conditions [ 1 ] = = false )
{
if (
2021-08-26 06:58:36 -04:00
ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 4 ] - > Disabled ( ) = = false & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & & // root, now disabled
ParticleHandles [ 6 ] - > Disabled ( ) = = false & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
Conditions [ 1 ] = true ;
EXPECT_EQ ( ClusterMap . Num ( ) , 3 ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 3 ] , ParticleHandles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 1 ] , ParticleHandles [ 8 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 7 ] , ParticleHandles [ 2 ] } ) ) ;
2020-05-05 11:41:40 -04:00
}
}
else if ( Conditions [ 1 ] = = true & & Conditions [ 2 ] = = false )
{
if (
2021-08-26 06:58:36 -04:00
ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = false & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 4 ] - > Disabled ( ) = = false & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = false & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
Conditions [ 2 ] = true ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 3 ] , ParticleHandles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 1 ] , ParticleHandles [ 8 ] } ) ) ;
2020-05-05 11:41:40 -04:00
}
}
else if ( Conditions [ 2 ] = = true & & Conditions [ 3 ] = = false )
{
if (
2021-08-26 06:58:36 -04:00
ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 1 ] - > Disabled ( ) = = false & &
ParticleHandles [ 2 ] - > Disabled ( ) = = false & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 4 ] - > Disabled ( ) = = false & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
2021-08-26 06:58:36 -04:00
ParticleHandles [ 8 ] - > Disabled ( ) = = false )
2020-05-05 11:41:40 -04:00
{
Conditions [ 3 ] = true ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 3 ] , ParticleHandles [ 0 ] } ) ) ;
2020-05-05 11:41:40 -04:00
}
}
else if ( Conditions [ 3 ] = = true )
{
// fLT_MAX strain so last cluster should never break.
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ParticleHandles [ 0 ] - > Disabled ( ) = = true ) ;
2020-05-05 11:41:40 -04:00
EXPECT_TRUE ( ParticleHandles [ 1 ] - > Disabled ( ) = = false ) ;
EXPECT_TRUE ( ParticleHandles [ 2 ] - > Disabled ( ) = = false ) ;
EXPECT_TRUE ( ParticleHandles [ 3 ] - > Disabled ( ) = = true ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ParticleHandles [ 4 ] - > Disabled ( ) = = false ) ;
EXPECT_TRUE ( ParticleHandles [ 5 ] - > Disabled ( ) = = true ) ;
2020-05-05 11:41:40 -04:00
EXPECT_TRUE ( ParticleHandles [ 6 ] - > Disabled ( ) = = true ) ;
EXPECT_TRUE ( ParticleHandles [ 7 ] - > Disabled ( ) = = true ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ParticleHandles [ 8 ] - > Disabled ( ) = = false ) ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
2021-08-26 06:58:36 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 3 ] , ParticleHandles [ 0 ] } ) ) ;
2020-05-05 11:41:40 -04:00
}
}
for ( int i = 0 ; i < Conditions . Num ( ) ; i + + )
{
2021-08-26 07:01:50 -04:00
//EXPECT_TRUE(Conditions[i]);
2020-05-05 11:41:40 -04:00
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_KinematicAnchor )
2020-05-05 11:41:40 -04:00
{
// Test : Set one element kinematic. When the cluster breaks the elements that do not contain the kinematic
// rigid body should be dynamic, while the clusters that contain the kinematic body should remain
// kinematic.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 20.f ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 30.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 40.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 50.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 60.f ) ) , FVector ( 1.0 ) ) ) ;
2021-08-26 06:58:36 -04:00
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 5 , { 4 , 3 } , true , false ) ; // just validate at end of construction
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 6 , { 5 , 2 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 7 , { 6 , 1 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
FGeometryCollectionClusteringUtility : : ValidateResults ( RestCollection . Get ( ) ) ;
2020-05-05 11:41:40 -04:00
2021-08-26 06:58:36 -04:00
//GeometryCollectionAlgo::PrintParentHierarchy(RestCollection.Get());
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 50.0 , 50.0 , 50.0 , FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
2022-05-11 12:14:04 -04:00
Collection - > DynamicCollection - > template ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) ;
FReal CurrentRigidDistance = 0 ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Staged conditions
// Initial state should set up the heirachy correctly, leaving correct disabled flags on frame 1
bool bValidInitialState = false ;
// After releasing particle 8, the states should be updated on frame 2
bool bParticle8SucessfulRelease = false ;
// After releasing particle 8, the states should be updated on frame 4
bool bParticle7SucessfulRelease = false ;
// After simulating post-release the states should match frame 4
bool bValidFinalActiveState = false ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Tick once to fush commands
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ClusterHandles = Collection - > PhysObject - > GetSolverClusterHandles ( ) ;
2020-05-05 11:41:40 -04:00
2022-01-03 16:19:33 -05:00
FRigidClustering & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const FRigidClustering : : FClusterMap & ClusterMap = Clustering . GetChildrenMap ( ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Verify that the parent-child relationship is reflected in the clustering hierarchy
// Tree should be:
//
// 8
/ / / \
// 7 0
/ / / \
// 6 1
/ / / \
// 5 2
/ / / \
// 4 3
//
// Entire cluster is kinematic due to particle 1
//
2020-05-05 11:41:40 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 7 ] , ParticleHandles [ 0 ] } ) ) ;
2021-08-17 19:58:19 -04:00
// Storage for positions for particles 0, 1, 6 for testing assumptions
FVector Ref0 ;
FVector Ref1 ;
FVector Ref6 ;
2020-05-05 11:41:40 -04:00
for ( int Frame = 1 ; Frame < 10 ; Frame + + )
{
UnitTest . Advance ( ) ;
2020-06-23 18:40:00 -04:00
// On frames 2 and 4, deactivate particles 8 and 7, releasing their children (7,0 then 6,1)
2020-05-05 11:41:40 -04:00
if ( Frame = = 2 )
{
2020-06-23 18:40:00 -04:00
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . DeactivateClusterParticle ( ParticleHandles [ 8 ] ) ;
2020-05-05 11:41:40 -04:00
}
if ( Frame = = 4 )
{
2020-06-23 18:40:00 -04:00
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . DeactivateClusterParticle ( ParticleHandles [ 7 ] ) ;
2020-05-05 11:41:40 -04:00
}
2020-06-23 18:40:00 -04:00
// Verify that the kinematic particle remains kinematic (InvMass == 0.0)
// and the the dynamic particles have a non-zero inv mass
2021-02-03 14:57:28 -04:00
EXPECT_NE ( ParticleHandles [ 0 ] - > InvM ( ) , 0 ) ; // dynamic rigid
EXPECT_EQ ( ParticleHandles [ 1 ] - > InvM ( ) , 0 ) ; // kinematic rigid
EXPECT_NE ( ParticleHandles [ 2 ] - > InvM ( ) , 0 ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 3 ] - > InvM ( ) , 0 ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 4 ] - > InvM ( ) , 0 ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 5 ] - > InvM ( ) , 0 ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 6 ] - > InvM ( ) , 0 ) ; // dynamic cluster
2020-05-05 11:41:40 -04:00
2021-08-17 19:58:19 -04:00
2020-06-23 18:40:00 -04:00
if ( ! bValidInitialState & & Frame = = 1 )
2020-05-05 11:41:40 -04:00
{
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
ParticleHandles [ 8 ] - > Disabled ( ) = = false )
{
2020-06-23 18:40:00 -04:00
bValidInitialState = true ;
Ref0 = ParticleHandles [ 0 ] - > X ( ) ;
Ref1 = ParticleHandles [ 1 ] - > X ( ) ;
Ref6 = ParticleHandles [ 6 ] - > X ( ) ;
// Test kinematic particles have valid (0.0) inverse mass and have the kinematic object state set
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Kinematic ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Kinematic ) ; // kinematic cluster
}
}
2020-06-23 18:40:00 -04:00
else if ( bValidInitialState & & ! bParticle8SucessfulRelease & & Frame = = 2 )
2020-05-05 11:41:40 -04:00
{
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = false & &
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
2020-06-23 18:40:00 -04:00
bParticle8SucessfulRelease = true ;
FVector X0 = ParticleHandles [ 0 ] - > X ( ) ;
FVector X1 = ParticleHandles [ 1 ] - > X ( ) ;
FVector X6 = ParticleHandles [ 6 ] - > X ( ) ;
2020-05-05 11:41:40 -04:00
2021-05-05 15:07:25 -04:00
FVector X00 = Ref0 ;
FVector X11 = Ref1 ;
FVector X66 = Ref6 ;
2021-08-26 06:58:36 -04:00
check ( ! X0 . ContainsNaN ( ) ) ;
check ( ! Ref0 . ContainsNaN ( ) ) ;
check ( FMath : : IsFinite ( X0 . Size ( ) ) ) ;
check ( FMath : : IsFinite ( Ref0 . Size ( ) ) ) ;
check ( FMath : : IsFinite ( X0 . Size ( ) - Ref0 . Size ( ) ) ) ;
2021-05-05 15:07:25 -04:00
check ( FMath : : IsFinite ( FMath : : Abs ( X0 . Size ( ) - X00 . Size ( ) ) ) ) ;
2020-06-23 18:40:00 -04:00
EXPECT_NEAR ( FMath : : Abs ( X0 . Size ( ) - Ref0 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ; // << *FString("Kinematic body1 moved");
2021-05-05 15:07:25 -04:00
check ( FMath : : IsFinite ( FMath : : Abs ( X1 . Size ( ) - X11 . Size ( ) ) ) ) ;
2020-06-23 18:40:00 -04:00
EXPECT_NEAR ( FMath : : Abs ( X1 . Size ( ) - Ref1 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ; // << *FString("Kinematic body2 moved");
2021-05-05 15:07:25 -04:00
check ( FMath : : IsFinite ( FMath : : Abs ( X6 . Size ( ) - X66 . Size ( ) ) ) ) ;
2020-06-23 18:40:00 -04:00
EXPECT_NEAR ( FMath : : Abs ( X6 . Size ( ) - Ref6 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ; // << *FString("Kinematic body7 moved");
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Test kinematic particles have valid (0.0) inverse mass and have the kinematic object state set
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Kinematic ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Kinematic ) ; // kinematic cluster
2020-06-23 18:40:00 -04:00
// Test that after declustering the new cluster hierarchy is what we expect
// Tree should be:
//
// 7 Removed: 8 (Disabled)
/ / / \ \
// 6 1 0 (Now unclustered)
/ / / \
// 5 2
/ / / \
// 4 3
//
// 8 has been removed, zero is dynamic and the remaining tree is kinematic due to particle 1
//
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ClusterMap . Num ( ) , 3 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
}
}
2020-06-23 18:40:00 -04:00
else if ( bParticle8SucessfulRelease & & ! bParticle7SucessfulRelease & & Frame = = 4 )
2020-05-05 11:41:40 -04:00
{
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
ParticleHandles [ 1 ] - > Disabled ( ) = = false & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = false & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
2020-06-23 18:40:00 -04:00
bParticle7SucessfulRelease = true ;
FVector X0 = ParticleHandles [ 0 ] - > X ( ) ;
FVector X1 = ParticleHandles [ 1 ] - > X ( ) ;
FVector X6 = ParticleHandles [ 6 ] - > X ( ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// 0 is a dynamic unclustered body (was owned by cluster 8), check that it's moved since declustering
EXPECT_GT ( FMath : : Abs ( X0 . Size ( ) - Ref0 . Size ( ) ) , KINDA_SMALL_NUMBER ) ;
// 1 is a kinematic unclustered body (was owned by cluster 7), check that it's stayed in place
EXPECT_NEAR ( FMath : : Abs ( X1 . Size ( ) - Ref1 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
// 6 is a dynamic cluster (was owned by cluster 7). Now that 1 is not a part of the cluster
// however it's just been declustered so make sure it's still near the starting location
EXPECT_NEAR ( FMath : : Abs ( X6 . Size ( ) - Ref6 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
// Check the newly disabled 7 is still kinematic
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Kinematic ) ; // kinematic cluster
2020-06-23 18:40:00 -04:00
// Test that after declustering the new cluster hierarchy is what we expect
// Tree should be:
//
// 6 Removed: 7 (disabled)
/ / / \ \
// 5 2 1 (declustered, but kinematic)
/ / / \
// 4 3
//
// 7 has been removed, 1 is kinematic and the rest of the tree is dynamic as the kinematic element is
// no longer in the cluster
//
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
}
}
2020-06-23 18:40:00 -04:00
else if ( bParticle7SucessfulRelease & & ! bValidFinalActiveState & & Frame = = 6 )
{
2020-05-05 11:41:40 -04:00
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
ParticleHandles [ 1 ] - > Disabled ( ) = = false & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = false & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
2020-06-23 18:40:00 -04:00
bValidFinalActiveState = true ;
FVector X0 = ParticleHandles [ 0 ] - > X ( ) ;
FVector X1 = ParticleHandles [ 1 ] - > X ( ) ;
FVector X6 = ParticleHandles [ 6 ] - > X ( ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// 0 is a dynamic unclustered body (was owned by cluster 8), check that it's moved since declustering
EXPECT_GT ( FMath : : Abs ( X0 . Size ( ) - Ref0 . Size ( ) ) , KINDA_SMALL_NUMBER ) ;
// 1 is a kinematic unclustered body (was owned by cluster 7), check that it's stayed in place
EXPECT_NEAR ( FMath : : Abs ( X1 . Size ( ) - Ref1 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
// 6 is a dynamic cluster (was owned by cluster 7). Now that 1 is not a part of the cluster
// it is dynamic, check that it has moved since declustering
EXPECT_GT ( FMath : : Abs ( X6 . Size ( ) - Ref6 . Size ( ) ) , KINDA_SMALL_NUMBER ) ;
// Check the previously declustered 7 is still kinematic
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Kinematic ) ; // kinematic cluster
2020-06-23 18:40:00 -04:00
// Test that the tree is still the same after the final decluster operation.
// Tree should be:
//
// 6
/ / / \
// 5 2
/ / / \
// 4 3
//
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
}
}
}
2020-06-23 18:40:00 -04:00
// Test our staged conditions
// Initial state should set up the heirachy correctly, leaving correct disabled flags on frame 1
EXPECT_TRUE ( bValidInitialState ) ;
// After releasing particle 8, the states should be updated on frame 2
EXPECT_TRUE ( bParticle8SucessfulRelease ) ;
// After releasing particle 8, the states should be updated on frame 4
EXPECT_TRUE ( bParticle7SucessfulRelease ) ;
// After simulating post-release the states should match frame 4
EXPECT_TRUE ( bValidFinalActiveState ) ;
2020-05-05 11:41:40 -04:00
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_StaticAnchor )
2020-05-05 11:41:40 -04:00
{
// Test : Set one element static. When the cluster breaks the elements that do not contain the static
// rigid body should be dynamic, while the clusters that contain the static body should remain
// static.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 20.f ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 30.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 40.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 50.f ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 60.f ) ) , FVector ( 1.0 ) ) ) ;
2021-08-26 06:58:36 -04:00
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 5 , { 4 , 3 } , true , false ) ; // just validate at end of construction
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 6 , { 5 , 2 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterBonesUnderNewNode ( RestCollection . Get ( ) , 7 , { 6 , 1 } , true , false ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
FGeometryCollectionClusteringUtility : : ValidateResults ( RestCollection . Get ( ) ) ;
2020-05-05 11:41:40 -04:00
2021-08-26 06:58:36 -04:00
//GeometryCollectionAlgo::PrintParentHierarchy(RestCollection.Get());
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 50.0 , 50.0 , 50.0 , FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
2022-05-11 12:14:04 -04:00
Collection - > DynamicCollection - > template ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Static ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) ;
FReal CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Staged conditions
// Initial state should set up the hierachy correctly, leaving correct disabled flags on frame 1
bool bValidInitialState = false ;
// After releasing particle 8, the states should be updated on frame 2
bool bParticle8SucessfulRelease = false ;
// After releasing particle 8, the states should be updated on frame 4
bool bParticle7SucessfulRelease = false ;
// After simulating post-release the states should match frame 4
bool bValidFinalActiveState = false ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Tick once to fush commands
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ClusterHandles = Collection - > PhysObject - > GetSolverClusterHandles ( ) ;
2020-05-05 11:41:40 -04:00
2022-01-03 16:19:33 -05:00
FRigidClustering & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const FRigidClustering : : FClusterMap & ClusterMap = Clustering . GetChildrenMap ( ) ;
2020-06-23 18:40:00 -04:00
// Verify that the parent-child relationship is reflected in the clustering hierarchy
// Tree should be:
//
// 8
/ / / \
// 7 0
/ / / \
// 6 1
/ / / \
// 5 2
/ / / \
// 4 3
//
// Entire cluster is kinematic due to particle 1
//
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 8 ] , { ParticleHandles [ 7 ] , ParticleHandles [ 0 ] } ) ) ;
// Storage for positions for particles 0, 1, 6 for testing assumptions
FVector Ref0 ;
FVector Ref1 ;
FVector Ref6 ;
for ( int Frame = 1 ; Frame < 10 ; Frame + + )
2020-05-05 11:41:40 -04:00
{
UnitTest . Advance ( ) ;
2020-06-23 18:40:00 -04:00
// On frames 2 and 4, deactivate particles 8 and 7, releasing their children (7,0 then 6,1)
if ( Frame = = 2 )
{
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . DeactivateClusterParticle ( ParticleHandles [ 8 ] ) ;
}
if ( Frame = = 4 )
{
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . DeactivateClusterParticle ( ParticleHandles [ 7 ] ) ;
}
// Verify that the kinematic particle remains kinematic (InvMass == 0.0)
// and the the dynamic particles have a non-zero inv mass
2020-05-05 11:41:40 -04:00
EXPECT_NE ( ParticleHandles [ 0 ] - > InvM ( ) , 0.f ) ; // dynamic rigid
2020-06-23 18:40:00 -04:00
EXPECT_EQ ( ParticleHandles [ 1 ] - > InvM ( ) , 0.f ) ; // kinematic rigid
2020-05-05 11:41:40 -04:00
EXPECT_NE ( ParticleHandles [ 2 ] - > InvM ( ) , 0.f ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 3 ] - > InvM ( ) , 0.f ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 4 ] - > InvM ( ) , 0.f ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 5 ] - > InvM ( ) , 0.f ) ; // dynamic rigid
EXPECT_NE ( ParticleHandles [ 6 ] - > InvM ( ) , 0.f ) ; // dynamic cluster
2020-06-23 18:40:00 -04:00
if ( ! bValidInitialState & & Frame = = 1 )
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = true & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
ParticleHandles [ 8 ] - > Disabled ( ) = = false )
{
2020-06-23 18:40:00 -04:00
bValidInitialState = true ;
Ref0 = ParticleHandles [ 0 ] - > X ( ) ;
Ref1 = ParticleHandles [ 1 ] - > X ( ) ;
Ref6 = ParticleHandles [ 6 ] - > X ( ) ;
// Test static particles have valid (0.0) inverse mass and have the static object state set
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Static ) ; // Static cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Static ) ; // Static cluster
2020-05-05 11:41:40 -04:00
}
2020-06-23 18:40:00 -04:00
}
else if ( bValidInitialState & & ! bParticle8SucessfulRelease & & Frame = = 2 )
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 1 ] - > Disabled ( ) = = true & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = true & &
ParticleHandles [ 7 ] - > Disabled ( ) = = false & &
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
2020-06-23 18:40:00 -04:00
bParticle8SucessfulRelease = true ;
FVector X0 = ParticleHandles [ 0 ] - > X ( ) ;
FVector X1 = ParticleHandles [ 1 ] - > X ( ) ;
FVector X6 = ParticleHandles [ 6 ] - > X ( ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
EXPECT_NEAR ( FMath : : Abs ( X0 . Size ( ) - Ref0 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
EXPECT_NEAR ( FMath : : Abs ( X1 . Size ( ) - Ref1 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
EXPECT_NEAR ( FMath : : Abs ( X6 . Size ( ) - Ref6 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Test static particles have valid (0.0) inverse mass and have the static object state set
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
2020-06-23 18:40:00 -04:00
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Static ) ; // Static cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > InvM ( ) , 0.f ) ; // kinematic cluster
EXPECT_EQ ( ParticleHandles [ 8 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Static ) ; // Static cluster
// Test that after declustering the new cluster hierarchy is what we expect
// Tree should be:
//
// 7 Removed: 8 (Disabled)
/ / / \ \
// 6 1 0 (Now unclustered)
/ / / \
// 5 2
/ / / \
// 4 3
//
// 8 has been removed, zero is dynamic and the remaining tree is static due to particle 1
//
EXPECT_EQ ( ClusterMap . Num ( ) , 3 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 7 ] , { ParticleHandles [ 6 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
2020-05-05 11:41:40 -04:00
}
}
2020-06-23 18:40:00 -04:00
else if ( bParticle8SucessfulRelease & & ! bParticle7SucessfulRelease & & Frame = = 4 )
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
2020-05-05 11:41:40 -04:00
ParticleHandles [ 1 ] - > Disabled ( ) = = false & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = false & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
2020-06-23 18:40:00 -04:00
bParticle7SucessfulRelease = true ;
FVector X0 = ParticleHandles [ 0 ] - > X ( ) ;
FVector X1 = ParticleHandles [ 1 ] - > X ( ) ;
FVector X6 = ParticleHandles [ 6 ] - > X ( ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// 0 is a dynamic unclustered body (was owned by cluster 8), check that it's moved since declustering
EXPECT_GT ( FMath : : Abs ( X0 . Size ( ) - Ref0 . Size ( ) ) , KINDA_SMALL_NUMBER ) ;
// 1 is a static unclustered body (was owned by cluster 7), check that it's stayed in place
EXPECT_NEAR ( FMath : : Abs ( X1 . Size ( ) - Ref1 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
// 6 is a dynamic cluster (was owned by cluster 7) but it has just been declustered
// Test that it's still near the starting position
EXPECT_NEAR ( FMath : : Abs ( X6 . Size ( ) - Ref6 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
// Check the newly disabled 7 is still static
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // Static cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Static ) ; // Static cluster
// Test that after declustering the new cluster hierarchy is what we expect
// Tree should be:
//
// 6 Removed: 7 (disabled)
/ / / \ \
// 5 2 1 (declustered, but Static)
/ / / \
// 4 3
//
// 7 has been removed, 1 is static and the rest of the tree is dynamic as the static element is
// no longer in the cluster
//
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
}
}
else if ( bParticle7SucessfulRelease & & ! bValidFinalActiveState & & Frame = = 6 )
{
if ( ParticleHandles [ 0 ] - > Disabled ( ) = = false & &
ParticleHandles [ 1 ] - > Disabled ( ) = = false & &
ParticleHandles [ 2 ] - > Disabled ( ) = = true & &
ParticleHandles [ 3 ] - > Disabled ( ) = = true & &
ParticleHandles [ 4 ] - > Disabled ( ) = = true & &
ParticleHandles [ 5 ] - > Disabled ( ) = = true & &
ParticleHandles [ 6 ] - > Disabled ( ) = = false & &
ParticleHandles [ 7 ] - > Disabled ( ) = = true & &
ParticleHandles [ 8 ] - > Disabled ( ) = = true )
{
bValidFinalActiveState = true ;
FVector X0 = ParticleHandles [ 0 ] - > X ( ) ;
FVector X1 = ParticleHandles [ 1 ] - > X ( ) ;
FVector X6 = ParticleHandles [ 6 ] - > X ( ) ;
// 0 is a dynamic unclustered body (was owned by cluster 8), check that it's moved since declustering
EXPECT_GT ( FMath : : Abs ( X0 . Size ( ) - Ref0 . Size ( ) ) , KINDA_SMALL_NUMBER ) ;
// 1 is a static unclustered body (was owned by cluster 7), check that it's stayed in place
EXPECT_NEAR ( FMath : : Abs ( X1 . Size ( ) - Ref1 . Size ( ) ) , 0 , KINDA_SMALL_NUMBER ) ;
// 6 is a dynamic cluster (was owned by cluster 7). Now that 1 is not a part of the cluster
// it is dynamic, check that it has moved since declustering
EXPECT_GT ( FMath : : Abs ( X6 . Size ( ) - Ref6 . Size ( ) ) , KINDA_SMALL_NUMBER ) ;
// Check the previously declustered 7 is still static
EXPECT_EQ ( ParticleHandles [ 7 ] - > InvM ( ) , 0.f ) ; // Static cluster
EXPECT_EQ ( ParticleHandles [ 7 ] - > ObjectState ( ) , Chaos : : EObjectStateType : : Static ) ; // Static cluster
// Test that the tree is still the same after the final decluster operation.
// Tree should be:
//
// 6
/ / / \
// 5 2
/ / / \
// 4 3
//
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 6 ] , { ParticleHandles [ 5 ] , ParticleHandles [ 2 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 5 ] , { ParticleHandles [ 4 ] , ParticleHandles [ 3 ] } ) ) ;
2020-05-05 11:41:40 -04:00
}
}
}
2020-06-23 18:40:00 -04:00
// Test our staged conditions
// Initial state should set up the heirachy correctly, leaving correct disabled flags on frame 1
EXPECT_TRUE ( bValidInitialState ) ;
// After releasing particle 8, the states should be updated on frame 2
EXPECT_TRUE ( bParticle8SucessfulRelease ) ;
// After releasing particle 8, the states should be updated on frame 4
EXPECT_TRUE ( bParticle7SucessfulRelease ) ;
// After simulating post-release the states should match frame 4
EXPECT_TRUE ( bValidFinalActiveState ) ;
2020-05-05 11:41:40 -04:00
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_UnionClusters )
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
// Test : Joining collections using the ClusterGroupIndex by a particle dynamically created within the solver.
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody ( FVector ( - 2 , 0 , 3 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection2 = CreateClusteredBody ( FVector ( 2 , 0 , 3 ) ) ;
CreationParameters Params2 ;
Params2 . RestCollection = RestCollection2 ;
Params2 . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
Params2 . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params2 . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params2 . Simulating = true ;
Params2 . EnableClustering = true ;
Params2 . DamageThreshold = { FLT_MAX } ;
Params2 . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection2 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params2 ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . AddSimulationObject ( Collection2 ) ;
UnitTest . Initialize ( ) ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection = Collection - > DynamicCollection ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection2 = Collection2 - > DynamicCollection ;
2021-02-03 14:57:28 -04:00
TArray < FReal > Distances ;
2020-05-05 11:41:40 -04:00
TManagedArray < FTransform > & Transform = DynamicCollection - > Transform ;
TManagedArray < FTransform > & Transform2 = DynamicCollection2 - > Transform ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
const auto & ParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles . Handle ( 2 ) - > CastToRigidParticle ( ) , { ParticleHandles . Handle ( 1 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 0 ) - > CastToRigidParticle ( ) } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles . Handle ( 5 ) - > CastToRigidParticle ( ) , { ParticleHandles . Handle ( 4 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 3 ) - > CastToRigidParticle ( ) } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
for ( int Frame = 0 ; Frame < 100 ; Frame + + )
{
UnitTest . Advance ( ) ;
2020-09-01 14:07:48 -04:00
2020-05-05 11:41:40 -04:00
if ( Frame = = 0 )
{
TArray < FTransform > GlobalTransform ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection - > Transform , DynamicCollection - > Parent , GlobalTransform ) ;
TArray < FTransform > GlobalTransform2 ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , GlobalTransform2 ) ;
// build relative transforms distances
for ( int32 i = 0 ; i < ( int32 ) GlobalTransform . Num ( ) - 1 ; i + + )
{
for ( int j = 0 ; j < ( int32 ) GlobalTransform2 . Num ( ) - 1 ; j + + )
{
Distances . Add ( ( GlobalTransform [ i ] . GetTranslation ( ) - GlobalTransform2 [ j ] . GetTranslation ( ) ) . Size ( ) ) ;
}
}
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles . Handle ( 6 ) - > CastToRigidParticle ( ) , { ParticleHandles . Handle ( 1 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 0 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 3 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 4 ) - > CastToRigidParticle ( ) } ) ) ;
}
}
TArray < FTransform > GlobalTransform ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection - > Transform , DynamicCollection - > Parent , GlobalTransform ) ;
TArray < FTransform > GlobalTransform2 ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , GlobalTransform2 ) ;
// build relative transforms distances
2021-02-03 14:57:28 -04:00
TArray < FReal > Distances2 ;
2020-05-05 11:41:40 -04:00
for ( int32 i = 0 ; i < ( int32 ) GlobalTransform . Num ( ) - 1 ; i + + )
{
for ( int j = 0 ; j < ( int32 ) GlobalTransform2 . Num ( ) - 1 ; j + + )
{
Distances2 . Add ( ( GlobalTransform [ i ] . GetTranslation ( ) - GlobalTransform2 [ j ] . GetTranslation ( ) ) . Size ( ) ) ;
}
}
for ( int i = 0 ; i < Distances . Num ( ) / 2.0 ; i + + )
{
EXPECT_LT ( FMath : : Abs ( Distances [ i ] - Distances2 [ i ] ) , 0.1 ) ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_UnionClustersFalling )
2020-05-05 11:41:40 -04:00
{
// Test : Joining collections using the ClusterGroupIndex by a particle dynamically created within the solver.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody ( FVector ( - 2 , 0 , 3 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection2 = CreateClusteredBody ( FVector ( 2 , 0 , 3 ) ) ;
CreationParameters Params2 ;
Params2 . RestCollection = RestCollection2 ;
Params2 . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params2 . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params2 . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params2 . Simulating = true ;
Params2 . EnableClustering = true ;
Params2 . DamageThreshold = { FLT_MAX } ;
Params2 . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection2 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params2 ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . AddSimulationObject ( Collection2 ) ;
UnitTest . Initialize ( ) ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection = Collection - > DynamicCollection ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection2 = Collection2 - > DynamicCollection ;
2021-02-03 14:57:28 -04:00
TArray < FReal > Distances ;
2020-05-05 11:41:40 -04:00
TManagedArray < FTransform > & Transform = DynamicCollection - > Transform ;
TManagedArray < FTransform > & Transform2 = DynamicCollection2 - > Transform ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
const auto & ParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & Clustering , & ClusterMap , & ParticleHandles ] ( )
{
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles . Handle ( 2 ) - > CastToRigidParticle ( ) , { ParticleHandles . Handle ( 1 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 0 ) - > CastToRigidParticle ( ) } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles . Handle ( 5 ) - > CastToRigidParticle ( ) , { ParticleHandles . Handle ( 4 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 3 ) - > CastToRigidParticle ( ) } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
TArray < FTransform > PrevGlobalTransform ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection - > Transform , DynamicCollection - > Parent , PrevGlobalTransform ) ;
TArray < FTransform > PrevGlobalTransform2 ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , PrevGlobalTransform2 ) ;
for ( int Frame = 0 ; Frame < 100 ; Frame + + )
{
UnitTest . Advance ( ) ;
TArray < FTransform > GlobalTransform ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection - > Transform , DynamicCollection - > Parent , GlobalTransform ) ;
TArray < FTransform > GlobalTransform2 ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , GlobalTransform2 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles . Handle ( 6 ) - > CastToRigidParticle ( ) , { ParticleHandles . Handle ( 1 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 0 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 3 ) - > CastToRigidParticle ( ) , ParticleHandles . Handle ( 4 ) - > CastToRigidParticle ( ) } ) ) ;
EXPECT_TRUE ( DynamicCollection - > Parent [ 0 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection - > Parent [ 1 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection - > Parent [ 2 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection2 - > Parent [ 0 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection2 - > Parent [ 1 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection2 - > Parent [ 2 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( GlobalTransform [ 0 ] . GetTranslation ( ) . X = = PrevGlobalTransform [ 0 ] . GetTranslation ( ) . X ) ;
EXPECT_TRUE ( GlobalTransform [ 1 ] . GetTranslation ( ) . X = = PrevGlobalTransform [ 1 ] . GetTranslation ( ) . X ) ;
EXPECT_TRUE ( GlobalTransform [ 0 ] . GetTranslation ( ) . Y = = PrevGlobalTransform [ 0 ] . GetTranslation ( ) . Y ) ;
EXPECT_TRUE ( GlobalTransform [ 1 ] . GetTranslation ( ) . Y = = PrevGlobalTransform [ 1 ] . GetTranslation ( ) . Y ) ;
EXPECT_TRUE ( GlobalTransform [ 0 ] . GetTranslation ( ) . Z < PrevGlobalTransform [ 0 ] . GetTranslation ( ) . Z ) ;
EXPECT_TRUE ( GlobalTransform [ 1 ] . GetTranslation ( ) . Z < PrevGlobalTransform [ 1 ] . GetTranslation ( ) . Z ) ;
EXPECT_TRUE ( GlobalTransform2 [ 0 ] . GetTranslation ( ) . X = = PrevGlobalTransform2 [ 0 ] . GetTranslation ( ) . X ) ;
EXPECT_TRUE ( GlobalTransform2 [ 1 ] . GetTranslation ( ) . X = = PrevGlobalTransform2 [ 1 ] . GetTranslation ( ) . X ) ;
EXPECT_TRUE ( GlobalTransform2 [ 0 ] . GetTranslation ( ) . Y = = PrevGlobalTransform2 [ 0 ] . GetTranslation ( ) . Y ) ;
EXPECT_TRUE ( GlobalTransform2 [ 1 ] . GetTranslation ( ) . Y = = PrevGlobalTransform2 [ 1 ] . GetTranslation ( ) . Y ) ;
EXPECT_TRUE ( GlobalTransform2 [ 0 ] . GetTranslation ( ) . Z < PrevGlobalTransform2 [ 0 ] . GetTranslation ( ) . Z ) ;
EXPECT_TRUE ( GlobalTransform2 [ 1 ] . GetTranslation ( ) . Z < PrevGlobalTransform2 [ 1 ] . GetTranslation ( ) . Z ) ;
PrevGlobalTransform = GlobalTransform ;
PrevGlobalTransform2 = GlobalTransform2 ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_UnionClusterCollisions )
2020-05-05 11:41:40 -04:00
{
// Test : Joining collections using the ClusterGroupIndex by a particle dynamically created within the solver.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody ( FVector ( - 2 , 0 , 3 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection2 = CreateClusteredBody ( FVector ( 2 , 0 , 3 ) ) ;
CreationParameters Params2 ;
Params2 . RestCollection = RestCollection2 ;
Params2 . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params2 . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params2 . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params2 . Simulating = true ;
Params2 . EnableClustering = true ;
Params2 . DamageThreshold = { FLT_MAX } ;
Params2 . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection2 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params2 ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . AddSimulationObject ( Collection2 ) ;
2021-03-18 15:20:03 -04:00
UnitTest . AddSimulationObject ( TNewSimulationObject < GeometryType : : RigidFloor > : : Init ( ) - > template As < RigidBodyWrapper > ( ) ) ;
2020-06-23 18:40:00 -04:00
//make newsimobject set a full block filter on all shapes!
2020-05-05 11:41:40 -04:00
UnitTest . Initialize ( ) ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection = Collection - > DynamicCollection ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection2 = Collection2 - > DynamicCollection ;
2021-02-03 14:57:28 -04:00
TArray < FReal > Distances ;
2020-05-05 11:41:40 -04:00
TManagedArray < FTransform > & Transform = DynamicCollection - > Transform ;
TManagedArray < FTransform > & Transform2 = DynamicCollection2 - > Transform ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
const auto & ParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2021-12-13 22:40:54 -05:00
const TArrayCollectionArray < FRigidTransform3 > & ChildToParent = Clustering . GetChildToParentMap ( ) ;
2020-05-05 11:41:40 -04:00
2021-12-13 22:40:54 -05:00
FVector TestOffset ;
FVector InitialRootPosition ;
FVector RelativeChildOffsets [ 4 ] ;
2020-06-23 18:40:00 -04:00
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
const auto & CollectionParticles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
EXPECT_EQ ( CollectionParticles . Num ( ) , 3 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , CollectionParticles [ 2 ] , { CollectionParticles [ 1 ] , CollectionParticles [ 0 ] } ) ) ;
const auto & CollectionParticles2 = Collection2 - > PhysObject - > GetSolverParticleHandles ( ) ;
EXPECT_EQ ( CollectionParticles2 . Num ( ) , 3 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , CollectionParticles2 [ 2 ] , { CollectionParticles2 [ 1 ] , CollectionParticles2 [ 0 ] } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
for ( int Frame = 0 ; Frame < 100 ; Frame + + )
{
UnitTest . Advance ( ) ;
2020-09-01 14:07:48 -04:00
const auto & CollectionParticles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
EXPECT_EQ ( CollectionParticles . Num ( ) , 3 ) ;
const auto & CollectionParticles2 = Collection2 - > PhysObject - > GetSolverParticleHandles ( ) ;
const auto * Root = CollectionParticles [ 0 ] - > ClusterIds ( ) . Id ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
2020-09-01 14:07:48 -04:00
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Root , { CollectionParticles [ 0 ] , CollectionParticles [ 1 ] , CollectionParticles2 [ 0 ] , CollectionParticles2 [ 1 ] } ) ) ;
2020-05-05 11:41:40 -04:00
2021-12-13 22:40:54 -05:00
//
// TEST
// Validate that the relative translations stay the same
// for the union clustered children, and that the root actually
// moves.
//
if ( Frame = = 0 )
{
InitialRootPosition = Root - > X ( ) ;
RelativeChildOffsets [ 0 ] = CollectionParticles [ 0 ] - > X ( ) - Root - > X ( ) ;
RelativeChildOffsets [ 1 ] = CollectionParticles [ 1 ] - > X ( ) - Root - > X ( ) ;
RelativeChildOffsets [ 2 ] = CollectionParticles2 [ 0 ] - > X ( ) - Root - > X ( ) ;
RelativeChildOffsets [ 3 ] = CollectionParticles2 [ 1 ] - > X ( ) - Root - > X ( ) ;
}
else
{
FTransform RootTransform ( Root - > R ( ) , Root - > X ( ) ) ;
TArray < FTransform > GlobalTransform1 ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection - > Transform , DynamicCollection - > Parent , GlobalTransform1 ) ;
TArray < FTransform > GlobalTransform2 ;
GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , GlobalTransform2 ) ;
EXPECT_TRUE ( ! InitialRootPosition . Equals ( Root - > X ( ) ) ) ; // root moves
EXPECT_TRUE ( RelativeChildOffsets [ 0 ] . Equals ( GlobalTransform1 [ 0 ] . GetRelativeTransform ( RootTransform ) . GetTranslation ( ) ) ) ;
EXPECT_TRUE ( RelativeChildOffsets [ 1 ] . Equals ( GlobalTransform1 [ 1 ] . GetRelativeTransform ( RootTransform ) . GetTranslation ( ) ) ) ;
EXPECT_TRUE ( RelativeChildOffsets [ 2 ] . Equals ( GlobalTransform2 [ 0 ] . GetRelativeTransform ( RootTransform ) . GetTranslation ( ) ) ) ;
EXPECT_TRUE ( RelativeChildOffsets [ 3 ] . Equals ( GlobalTransform2 [ 1 ] . GetRelativeTransform ( RootTransform ) . GetTranslation ( ) ) ) ;
}
//
// TEST
// Validate that the children have been removed from the
// parenting hierarchy.
//
2020-05-05 11:41:40 -04:00
EXPECT_TRUE ( DynamicCollection - > Parent [ 0 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection - > Parent [ 1 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection - > Parent [ 2 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection2 - > Parent [ 0 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection2 - > Parent [ 1 ] = = INDEX_NONE ) ;
EXPECT_TRUE ( DynamicCollection2 - > Parent [ 2 ] = = INDEX_NONE ) ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_ReleaseClusterParticle_ClusteredNode )
2020-05-05 11:41:40 -04:00
{
// Test : Build to geometry collections, cluster them together, release the sub bodies of the first collection.
// ... should create a internal cluster with property transform mappings.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody ( FVector ( 0 , 0 , 100 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . ClusterGroupIndex = 1 ;
2021-03-05 19:27:14 -04:00
Params . ClusterConnectionMethod = Chaos : : FClusterCreationParameters : : EConnectionMethod : : DelaunayTriangulation ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection1 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection1 ) ;
TSharedPtr < FGeometryCollection > RestCollection2 = CreateClusteredBody ( FVector ( 0 , 0 , 200 ) ) ;
CreationParameters Params2 ;
Params2 . RestCollection = RestCollection2 ;
Params2 . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params2 . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params2 . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params2 . Simulating = true ;
Params2 . EnableClustering = true ;
Params2 . DamageThreshold = { FLT_MAX } ;
Params2 . ClusterGroupIndex = 1 ;
2021-03-05 19:27:14 -04:00
Params2 . ClusterConnectionMethod = Chaos : : FClusterCreationParameters : : EConnectionMethod : : DelaunayTriangulation ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection2 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params2 ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection2 ) ;
UnitTest . Initialize ( ) ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection1 = Collection1 - > DynamicCollection ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection2 = Collection2 - > DynamicCollection ;
TArray < FTransform > Collection1_InitialTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_InitialTM ) ;
TArray < FTransform > Collection2_InitialTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , Collection2_InitialTM ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & Collection1Handles = Collection1 - > PhysObject - > GetSolverParticleHandles ( ) ;
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & Collection2Handles = Collection2 - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
const auto & SovlerParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 6 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection2Handles [ 2 ] , { Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 7 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , SovlerParticleHandles . Handle ( 6 ) - > CastToRigidParticle ( ) , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] , Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
TArray < FTransform > Collection1_PreReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PreReleaseTM ) ;
TArray < FTransform > Collection2_PreReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , Collection2_PreReleaseTM ) ;
for ( int Idx = 0 ; Idx < Collection1_PreReleaseTM . Num ( ) - 1 ; Idx + + ) {
EXPECT_LT ( Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection1_InitialTM [ Idx ] . GetTranslation ( ) . Z ) ;
EXPECT_LT ( Collection2_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection2_InitialTM [ Idx ] . GetTranslation ( ) . Z ) ;
}
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . ReleaseClusterParticles ( { Collection1Handles [ 0 ] , Collection1Handles [ 1 ] } ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 8 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , SovlerParticleHandles . Handle ( 7 ) - > CastToRigidParticle ( ) , { Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 8 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , SovlerParticleHandles . Handle ( 7 ) - > CastToRigidParticle ( ) , { Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
TArray < FTransform > Collection1_PostReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PostReleaseTM ) ;
TArray < FTransform > Collection2_PostReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , Collection2_PostReleaseTM ) ;
for ( int Idx = 0 ; Idx < Collection1_PostReleaseTM . Num ( ) - 1 ; Idx + + ) {
EXPECT_LT ( Collection1_PostReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z ) ;
EXPECT_LT ( Collection2_PostReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection2_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z ) ;
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_ReleaseClusterParticle_ClusteredKinematicNode )
2020-06-23 18:40:00 -04:00
{
2020-05-05 11:41:40 -04:00
// Test : Build to geometry collections, cluster them together, release the sub bodies of the first collection.
2020-06-23 18:40:00 -04:00
// this should create a internal cluster with property transform mappings.
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody ( FVector ( 0 , 0 , 100 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . ClusterGroupIndex = 1 ;
2021-03-05 19:27:14 -04:00
Params . ClusterConnectionMethod = Chaos : : FClusterCreationParameters : : EConnectionMethod : : DelaunayTriangulation ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection1 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection1 ) ;
TSharedPtr < FGeometryCollection > RestCollection2 = CreateClusteredBody ( FVector ( 0 , 0 , 200 ) ) ;
CreationParameters Params2 ;
Params2 . RestCollection = RestCollection2 ;
Params2 . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params2 . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params2 . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params2 . Simulating = true ;
Params2 . EnableClustering = true ;
Params2 . DamageThreshold = { FLT_MAX } ;
Params2 . ClusterGroupIndex = 1 ;
2021-03-05 19:27:14 -04:00
Params2 . ClusterConnectionMethod = Chaos : : FClusterCreationParameters : : EConnectionMethod : : DelaunayTriangulation ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection2 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params2 ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection2 ) ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection1 = Collection1 - > DynamicCollection ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection2 = Collection2 - > DynamicCollection ;
2022-05-11 12:14:04 -04:00
DynamicCollection1 - > ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-05-05 11:41:40 -04:00
UnitTest . Initialize ( ) ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
TArray < FTransform > Collection1_InitialTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_InitialTM ) ;
TArray < FTransform > Collection2_InitialTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , Collection2_InitialTM ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & Collection1Handles = Collection1 - > PhysObject - > GetSolverParticleHandles ( ) ;
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & Collection2Handles = Collection2 - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
const auto & SovlerParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 6 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection2Handles [ 2 ] , { Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 7 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , SovlerParticleHandles . Handle ( 6 ) - > CastToRigidParticle ( ) , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] , Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
TArray < FTransform > Collection1_PreReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PreReleaseTM ) ;
TArray < FTransform > Collection2_PreReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , Collection2_PreReleaseTM ) ;
2020-06-23 18:40:00 -04:00
for ( int Idx = 0 ; Idx < Collection1_PreReleaseTM . Num ( ) - 1 ; Idx + + )
{
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection1_InitialTM [ Idx ] . GetTranslation ( ) . Z ) ;
EXPECT_EQ ( Collection2_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection2_InitialTM [ Idx ] . GetTranslation ( ) . Z ) ;
}
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . ReleaseClusterParticles ( { Collection1Handles [ 0 ] , Collection1Handles [ 1 ] } ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 8 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , SovlerParticleHandles . Handle ( 7 ) - > CastToRigidParticle ( ) , { Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 8 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , SovlerParticleHandles . Handle ( 7 ) - > CastToRigidParticle ( ) , { Collection2Handles [ 1 ] , Collection2Handles [ 0 ] } ) ) ;
// validate that DynamicCollection2 became dynamic and fell from the cluster.
TArray < FTransform > Collection1_PostReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PostReleaseTM ) ;
TArray < FTransform > Collection2_PostReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection2 - > Transform , DynamicCollection2 - > Parent , Collection2_PostReleaseTM ) ;
2020-06-23 18:40:00 -04:00
for ( int Idx = 0 ; Idx < Collection1_PostReleaseTM . Num ( ) - 1 ; Idx + + )
{
if ( Idx = = 1 )
{
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection1_PostReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z ) ; // the original kinematic should be frozen
2020-06-23 18:40:00 -04:00
}
2020-05-05 11:41:40 -04:00
else
2020-06-23 18:40:00 -04:00
{
2020-05-05 11:41:40 -04:00
EXPECT_LT ( Collection1_PostReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z ) ;
2020-06-23 18:40:00 -04:00
}
2020-05-05 11:41:40 -04:00
EXPECT_LT ( Collection2_PostReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection2_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z ) ;
}
}
2021-10-21 13:21:05 -04:00
// Create two boxes and wrap them in a clusterm and wrap that in a second cluster.
// Release the two boxes, and the boxes should fall. Both clusters should be empty and therefore disabled.
//
// @todo(chaos): this test is disabled. The outer cluster is not being disabled when the leafs are released.
// Fix when this functionality is supported again...
GTEST_TEST ( AllTraits , DISABLED_GeometryCollection_RigidBodies_ClusterTest_ReleaseClusterParticles_AllLeafNodes )
2020-05-05 11:41:40 -04:00
{
// Release the leaf nodes of a cluster. This test exercises the clusters ability to deactivate from the bottom up.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody_TwoParents_TwoBodies ( FVector ( 0 , 0 , 100 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
Params . ClusterGroupIndex = 0 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection1 = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryDynamicCollection > DynamicCollection1 = Collection1 - > DynamicCollection ;
2022-05-11 12:14:04 -04:00
DynamicCollection1 - > ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection1 ) ;
UnitTest . Initialize ( ) ;
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
TArray < FTransform > Collection1_InitialTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_InitialTM ) ;
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & Collection1Handles = Collection1 - > PhysObject - > GetSolverParticleHandles ( ) ;
2020-05-05 11:41:40 -04:00
const auto & SovlerParticleHandles = UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 3 ] , { Collection1Handles [ 2 ] } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 2 ] , { Collection1Handles [ 1 ] , Collection1Handles [ 0 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , Collection1Handles [ 3 ] , { Collection1Handles [ 2 ] } ) ) ;
TArray < FTransform > Collection1_PreReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PreReleaseTM ) ;
2020-06-23 18:40:00 -04:00
for ( int Idx = 0 ; Idx < Collection1_PreReleaseTM . Num ( ) - 1 ; Idx + + )
{
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection1_PreReleaseTM [ Idx ] . GetTranslation ( ) . Z , Collection1_InitialTM [ Idx ] . GetTranslation ( ) . Z ) ;
}
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . ReleaseClusterParticles ( { Collection1Handles [ 0 ] , Collection1Handles [ 1 ] } ) ;
2020-06-23 18:40:00 -04:00
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2020-06-23 18:40:00 -04:00
EXPECT_EQ ( SovlerParticleHandles . Size ( ) , 4 ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
2020-05-05 11:41:40 -04:00
// validate that DynamicCollection1 BODY 2 became dynamic and fell from the cluster.
TArray < FTransform > Collection1_PostReleaseTM ; GeometryCollectionAlgo : : GlobalMatrices ( DynamicCollection1 - > Transform , DynamicCollection1 - > Parent , Collection1_PostReleaseTM ) ;
2020-06-23 18:40:00 -04:00
EXPECT_NEAR ( Collection1_PostReleaseTM [ 1 ] . GetTranslation ( ) . Z , Collection1_PreReleaseTM [ 1 ] . GetTranslation ( ) . Z , KINDA_SMALL_NUMBER ) ; // the original kinematic should be frozen
EXPECT_LT ( Collection1_PostReleaseTM [ 0 ] . GetTranslation ( ) . Z , Collection1_PreReleaseTM [ 0 ] . GetTranslation ( ) . Z ) ;
2020-05-05 11:41:40 -04:00
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_RigidBodies_ClusterTest_ReleaseClusterParticles_ClusterNodeAndSubClusterNode )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody_TwoParents_TwoBodies ( FVector ( 0 , 0 , 100 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { FLT_MAX } ;
Params . MaxClusterLevel = 1 ;
Params . ClusterGroupIndex = 1 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryDynamicCollection > DynamicCollection = Collection - > DynamicCollection ;
2022-05-11 12:14:04 -04:00
DynamicCollection - > ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
2020-06-23 18:40:00 -04:00
UnitTest . Initialize ( ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// The tests below require a list of all the current particles which are abstracted away a little
// inside the solver particles handler. This helper just lets us auto cast to rigids as we know
// that's all that exists in the solver.
struct FRigidParticleWrapper
{
2021-02-03 14:57:28 -04:00
FRigidParticleWrapper ( TGeometryParticleHandles < FReal , 3 > & InParticlesRef )
2020-06-23 18:40:00 -04:00
: Particles ( InParticlesRef )
{ }
2021-02-03 14:57:28 -04:00
TGeometryParticleHandles < FReal , 3 > & Particles ;
2020-06-23 18:40:00 -04:00
2021-02-03 14:57:28 -04:00
TPBDRigidParticleHandle < FReal , 3 > * operator [ ] ( int32 InIndex )
2020-06-23 18:40:00 -04:00
{
return Particles . Handle ( InIndex ) - > CastToRigidParticle ( ) ;
}
} ;
FRigidParticleWrapper ParticleHandles ( UnitTest . Solver - > GetParticles ( ) . GetParticleHandles ( ) ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
2022-01-03 16:19:33 -05:00
FRigidClustering & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const FRigidClustering : : FClusterMap & ClusterMap = Clustering . GetChildrenMap ( ) ;
2020-05-05 11:41:40 -04:00
const Chaos : : TArrayCollectionArray < Chaos : : ClusterId > & ClusterIdsArray = Clustering . GetClusterIdsArray ( ) ;
2020-09-01 14:07:48 -04:00
UnitTest . Solver - > RegisterSimOneShotCallback ( [ & ] ( )
{
EXPECT_EQ ( ClusterMap . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 2 ] , { ParticleHandles [ 0 ] , ParticleHandles [ 1 ] } ) ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 4 ] , { ParticleHandles [ 2 ] } ) ) ;
} ) ;
2020-05-05 11:41:40 -04:00
2020-06-23 18:40:00 -04:00
// Test releasing a specific unioned cluster
// We end up with the following cluster tree
// 4
// |
// 2
/ / / \
// 1 0
// On frame 5 we tell particle 4 as a cluster parent to release its children (only 2) and verify the result
2020-05-05 11:41:40 -04:00
for ( int Frame = 1 ; Frame < 10 ; Frame + + )
{
UnitTest . Advance ( ) ;
if ( Frame = = 5 )
{
2020-06-23 18:40:00 -04:00
UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . ReleaseClusterParticles ( ParticleHandles [ 4 ] - > CastToClustered ( ) , nullptr , true ) ;
2020-05-05 11:41:40 -04:00
}
2020-06-23 18:40:00 -04:00
2020-05-05 11:41:40 -04:00
if ( Frame < 5 )
{
EXPECT_TRUE ( ParticleHandles [ 2 ] - > Disabled ( ) ) ;
2020-06-23 18:40:00 -04:00
EXPECT_NE ( ClusterIdsArray [ 0 ] . Id , nullptr ) ;
EXPECT_EQ ( ClusterIdsArray [ 1 ] . Id , nullptr ) ;
EXPECT_EQ ( ClusterIdsArray [ 2 ] . Id , nullptr ) ;
2020-05-05 11:41:40 -04:00
}
else
{
EXPECT_TRUE ( ! ParticleHandles [ 2 ] - > Disabled ( ) ) ;
2020-06-23 18:40:00 -04:00
EXPECT_EQ ( ClusterIdsArray [ 0 ] . Id , nullptr ) ;
EXPECT_EQ ( ClusterIdsArray [ 1 ] . Id , nullptr ) ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( ClusterIdsArray [ 2 ] . Id , nullptr ) ;
EXPECT_EQ ( ClusterMap . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMapContains ( ClusterMap , ParticleHandles [ 2 ] , { ParticleHandles [ 0 ] , ParticleHandles [ 1 ] } ) ) ;
}
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , DISABLED_GeometryCollection_RigidBodies_ClusterTest_RemoveOnFracture )
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
// Disabled as remove on fracture currently unimplemented for geometry collections. Potentially this should be deleted entirely.
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 , 0 , 0. ) ) , FVector ( 0 , - 10 , 10 ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 , 0 , 0. ) ) , FVector ( 0 , 10 , 10 ) ) , FVector ( 1.0 ) ) ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 2 ) ;
// this transform should have a zero scale after the simulation has run to the point of fracture
RestCollection - > SetFlags ( 1 , FGeometryCollection : : FS_RemoveOnFracture ) ;
FGeometryCollectionClusteringUtility : : ClusterAllBonesUnderNewRoot ( RestCollection . Get ( ) ) ;
EXPECT_EQ ( RestCollection - > Transform . Num ( ) , 3 ) ;
RestCollection - > Transform [ 2 ] = FTransform ( FQuat : : MakeFromEuler ( FVector ( 90.f , 0 , 0. ) ) , FVector ( 0 , 0 , 40 ) ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 0.1f } ;
Params . RemoveOnFractureEnabled = true ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
FRadialFalloff * FalloffField = new FRadialFalloff ( ) ;
FalloffField - > Magnitude = 10.5 ;
FalloffField - > Radius = 100.0 ;
FalloffField - > Position = FVector ( 0.0 , 0.0 , 0.0 ) ;
FalloffField - > Falloff = EFieldFalloffType : : Field_FallOff_None ;
TSharedPtr < FGeometryDynamicCollection > DynamicCollection = Collection - > DynamicCollection ;
2022-05-11 12:14:04 -04:00
DynamicCollection - > ModifyAttribute < int32 > ( " DynamicState " , FGeometryCollection : : TransformGroup ) [ 1 ] = ( uint8 ) EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
2020-06-23 18:40:00 -04:00
UnitTest . Initialize ( ) ;
2020-05-05 11:41:40 -04:00
auto & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
TManagedArray < FTransform > & Transform = Collection - > DynamicCollection - > Transform ;
2021-02-03 14:57:28 -04:00
FReal StartingRigidDistance = ( Transform [ 1 ] . GetTranslation ( ) - Transform [ 0 ] . GetTranslation ( ) ) . Size ( ) , CurrentRigidDistance = 0.f ;
2020-05-05 11:41:40 -04:00
// #todo: is this even used?
/*
2021-02-03 14:57:28 -04:00
Chaos : : TArrayCollectionArray < FReal > & InternalStrain = Clustering . GetStrainArray ( ) ;
2020-05-05 11:41:40 -04:00
*/
FName TargetName = GetFieldPhysicsName ( EFieldPhysicsType : : Field_ExternalClusterStrain ) ;
FFieldSystemCommand Command ( TargetName , FalloffField - > NewCopy ( ) ) ;
FFieldSystemMetaDataProcessingResolution * ResolutionData = new FFieldSystemMetaDataProcessingResolution ( EFieldResolutionType : : Field_Resolution_Maximum ) ;
Command . MetaData . Add ( FFieldSystemMetaData : : EMetaType : : ECommandData_ProcessingResolution , TUniquePtr < FFieldSystemMetaDataProcessingResolution > ( ResolutionData ) ) ;
2021-01-08 19:56:07 -04:00
UnitTest . Solver - > GetPerSolverField ( ) . AddTransientCommand ( Command ) ;
2020-05-05 11:41:40 -04:00
FVector Scale = Transform [ 1 ] . GetScale3D ( ) ;
EXPECT_NEAR ( Scale . X , 1.0f , SMALL_NUMBER ) ;
EXPECT_NEAR ( Scale . Y , 1.0f , SMALL_NUMBER ) ;
EXPECT_NEAR ( Scale . Z , 1.0f , SMALL_NUMBER ) ;
UnitTest . Advance ( ) ;
2021-01-08 19:56:07 -04:00
UnitTest . Solver - > GetPerSolverField ( ) . AddTransientCommand ( { TargetName , FalloffField - > NewCopy ( ) } ) ;
2020-05-05 11:41:40 -04:00
UnitTest . Advance ( ) ;
FVector Scale2 = Transform [ 1 ] . GetScale3D ( ) ;
// geometry hidden by 0 scaling on transform
EXPECT_NEAR ( Scale2 . X , 0.0f , SMALL_NUMBER ) ;
EXPECT_NEAR ( Scale2 . Y , 0.0f , SMALL_NUMBER ) ;
EXPECT_NEAR ( Scale2 . Z , 0.0f , SMALL_NUMBER ) ;
delete FalloffField ;
}
2021-08-26 07:01:50 -04:00
GTEST_TEST ( AllTraits , DISABLED_GeometryCollection_RigidBodiess_ClusterTest_MaxClusterLevel_1 )
2021-08-26 06:59:01 -04:00
{
FFramework UnitTest ;
// Create hierarchy
TSharedPtr < FGeometryCollection > RestCollection ;
RestCollection = GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 0 , 0 , 0 ) ) , FVector ( 1.0 ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 100 , 0 , 0 ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 200 , 0 , 0 ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 300 , 0 , 0 ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 400 , 0 , 0 ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AppendGeometry ( * GeometryCollection : : MakeCubeElement ( FTransform ( FQuat : : MakeFromEuler ( FVector ( 0.f ) ) , FVector ( 500 , 0 , 0 ) ) , FVector ( 1.0 ) ) ) ;
RestCollection - > AddElements ( 7 , FGeometryCollection : : TransformGroup ) ;
RestCollection - > Transform [ 10 ] . SetTranslation ( FVector ( 0 , 0 , 0 ) ) ;
RestCollection - > SimulationType [ 0 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
RestCollection - > SimulationType [ 1 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
RestCollection - > SimulationType [ 2 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
RestCollection - > SimulationType [ 3 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
RestCollection - > SimulationType [ 4 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
RestCollection - > SimulationType [ 5 ] = FGeometryCollection : : ESimulationTypes : : FST_Rigid ;
RestCollection - > SimulationType [ 6 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
RestCollection - > SimulationType [ 7 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
RestCollection - > SimulationType [ 8 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
RestCollection - > SimulationType [ 9 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
RestCollection - > SimulationType [ 10 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
RestCollection - > SimulationType [ 11 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
RestCollection - > SimulationType [ 12 ] = FGeometryCollection : : ESimulationTypes : : FST_Clustered ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 6 , { 11 } ) ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 7 , { 3 , 4 , 5 } ) ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 8 , { 6 } ) ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 9 , { 7 } ) ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 10 , { 9 , 8 } ) ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 11 , { 12 } ) ;
GeometryCollectionAlgo : : ParentTransforms ( RestCollection . Get ( ) , 12 , { 0 , 1 , 2 } ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . DamageThreshold = { 100.0f , 4.0f , 2.0f } ;
Params . MaxClusterLevel = 3 ;
Params . ClusterGroupIndex = 0 ;
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
UnitTest . AddSimulationObject ( Collection ) ;
UnitTest . Initialize ( ) ;
UnitTest . Advance ( ) ;
FRadialFalloff * FalloffField = new FRadialFalloff ( ) ;
FalloffField - > Magnitude = 104.0 ;
FalloffField - > Radius = 10000.0 ;
FalloffField - > Position = FVector ( 0.0 , 0.0 , 0.0 ) ;
FalloffField - > Falloff = EFieldFalloffType : : Field_FallOff_None ;
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2022-01-03 16:19:33 -05:00
Chaos : : FRigidClustering & Clustering = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) ;
2021-08-26 06:59:01 -04:00
const auto & ClusterMap = Clustering . GetChildrenMap ( ) ;
auto & x = UnitTest . Solver - > GetEvolution ( ) - > GetRigidClustering ( ) . GetStrainArray ( ) ;
{
EXPECT_EQ ( ClusterMap . Num ( ) , 5 ) ;
EXPECT_EQ ( ClusterMap [ ParticleHandles [ 6 ] ] . Num ( ) , 3 ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 6 ] ] . Contains ( ParticleHandles [ 0 ] ) ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 6 ] ] . Contains ( ParticleHandles [ 1 ] ) ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 6 ] ] . Contains ( ParticleHandles [ 2 ] ) ) ;
EXPECT_EQ ( ClusterMap [ ParticleHandles [ 7 ] ] . Num ( ) , 3 ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 7 ] ] . Contains ( ParticleHandles [ 3 ] ) ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 7 ] ] . Contains ( ParticleHandles [ 4 ] ) ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 7 ] ] . Contains ( ParticleHandles [ 5 ] ) ) ;
EXPECT_EQ ( ClusterMap [ ParticleHandles [ 8 ] ] . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 8 ] ] . Contains ( ParticleHandles [ 6 ] ) ) ;
EXPECT_EQ ( ClusterMap [ ParticleHandles [ 9 ] ] . Num ( ) , 1 ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 9 ] ] . Contains ( ParticleHandles [ 7 ] ) ) ;
EXPECT_EQ ( ClusterMap [ ParticleHandles [ 10 ] ] . Num ( ) , 2 ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 10 ] ] . Contains ( ParticleHandles [ 8 ] ) ) ;
EXPECT_TRUE ( ClusterMap [ ParticleHandles [ 10 ] ] . Contains ( ParticleHandles [ 9 ] ) ) ;
}
EXPECT_TRUE ( ParticleHandles [ 6 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 7 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 8 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 9 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 10 ] - > Disabled ( ) ) ;
// {100, 4, 2} -> {4, 2}
FName TargetName = GetFieldPhysicsName ( EFieldPhysicsType : : Field_ExternalClusterStrain ) ;
UnitTest . Solver - > GetPerSolverField ( ) . AddTransientCommand ( { TargetName , FalloffField - > NewCopy ( ) } ) ;
UnitTest . Advance ( ) ;
EXPECT_TRUE ( ParticleHandles [ 6 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 7 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 8 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 9 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 10 ] - > Disabled ( ) ) ;
// {4, 2} -> {4, 2} (beyond max cluster level)
UnitTest . Solver - > GetPerSolverField ( ) . AddTransientCommand ( { TargetName , FalloffField - > NewCopy ( ) } ) ;
UnitTest . Advance ( ) ;
EXPECT_TRUE ( ParticleHandles [ 0 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 1 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 2 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 3 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 4 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 5 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 6 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 7 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 8 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 9 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 10 ] - > Disabled ( ) ) ;
// {4, 2} -> {4, 2} (beyond max cluster level)
// but this time, force internal reordering via internal strain.
TargetName = GetFieldPhysicsName ( EFieldPhysicsType : : Field_InternalClusterStrain ) ; // Note: now internal strain
FalloffField - > Magnitude = - 3.0 ;
UnitTest . Solver - > GetPerSolverField ( ) . AddTransientCommand ( { TargetName , FalloffField - > NewCopy ( ) } ) ;
UnitTest . Advance ( ) ;
EXPECT_TRUE ( ParticleHandles [ 0 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 1 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 2 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 3 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 4 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 5 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 6 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 7 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 8 ] - > Disabled ( ) ) ;
EXPECT_FALSE ( ParticleHandles [ 9 ] - > Disabled ( ) ) ;
EXPECT_TRUE ( ParticleHandles [ 10 ] - > Disabled ( ) ) ;
{ // Check if level 3 rigids (children) are still clustered despite internal strain breaking level 2 clusters (parent)
2021-08-26 07:01:50 -04:00
//EXPECT_EQ(ClusterMap[ParticleHandles[6]].Num(), 3);
//EXPECT_TRUE(ClusterMap[ParticleHandles[6]].Contains(ParticleHandles[0]));
//EXPECT_TRUE(ClusterMap[ParticleHandles[6]].Contains(ParticleHandles[1]));
//EXPECT_TRUE(ClusterMap[ParticleHandles[6]].Contains(ParticleHandles[2]));
//EXPECT_EQ(ClusterMap[ParticleHandles[7]].Num(), 3);
//EXPECT_TRUE(ClusterMap[ParticleHandles[7]].Contains(ParticleHandles[3]));
//EXPECT_TRUE(ClusterMap[ParticleHandles[7]].Contains(ParticleHandles[4]));
//EXPECT_TRUE(ClusterMap[ParticleHandles[7]].Contains(ParticleHandles[5]));
2021-08-26 06:59:01 -04:00
}
}
2020-05-05 11:41:40 -04:00
2021-08-26 07:01:50 -04:00
GTEST_TEST ( AllTraits , DISABLED_GeometryCollection_RigidBodiess_ClusterTest_ParticleImplicitCollisionGeometry )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
TSharedPtr < FGeometryCollection > RestCollection = CreateClusteredBody_FracturedGeometry ( ) ;
CreationParameters Params ;
Params . RestCollection = RestCollection ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . Simulating = true ;
Params . EnableClustering = true ;
Params . CollisionGroup = - 1 ;
2021-08-26 06:58:14 -04:00
Params . CollisionParticleFraction = 0.70f ;
2020-05-05 11:41:40 -04:00
Params . MinLevelSetResolution = 15 ;
Params . MaxLevelSetResolution = 20 ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSuppliedRestCollection > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
2021-08-26 06:58:14 -04:00
UnitTest . Initialize ( ) ;
2020-05-05 11:41:40 -04:00
2021-08-26 06:58:14 -04:00
// We can get the size of an original CollisionParticles by storing the Simplicials before any internal resizing.
2020-05-05 11:41:40 -04:00
typedef TUniquePtr < FCollisionStructureManager : : FSimplicial > FSimplicialPointer ;
const TManagedArray < FSimplicialPointer > & Simplicials = RestCollection - > template GetAttribute < FSimplicialPointer > ( FGeometryDynamicCollection : : SimplicialsAttribute , FTransformCollection : : TransformGroup ) ;
2021-08-26 06:58:14 -04:00
UnitTest . Advance ( ) ; // this call triggers the array resize based on the fraction
2020-05-05 11:41:40 -04:00
2021-08-26 06:58:14 -04:00
// Test non-clustered bodies
2021-02-03 14:57:28 -04:00
TArray < Chaos : : TPBDRigidClusteredParticleHandle < FReal , 3 > * > & ParticleHandles = Collection - > PhysObject - > GetSolverParticleHandles ( ) ;
2021-08-26 06:58:14 -04:00
int32 NumCollisionParticles , ExpectedNumCollisionParticles ;
for ( int i = 0 ; i < ParticleHandles . Num ( ) ; i + + )
2020-05-05 11:41:40 -04:00
{
2021-08-26 06:58:14 -04:00
if ( Collection - > RestCollection - > SimulationType [ i ] = = FGeometryCollection : : ESimulationTypes : : FST_Rigid )
{
NumCollisionParticles = ParticleHandles [ i ] - > CollisionParticlesSize ( ) ; // resized
ExpectedNumCollisionParticles = ( int32 ) Simplicials [ i ] - > Size ( ) * Params . CollisionParticleFraction ;
2021-08-26 07:01:50 -04:00
//EXPECT_EQ(ExpectedNumCollisionParticles, NumCollisionParticles);
//EXPECT_FALSE(NumCollisionParticles == 0.0f);
//EXPECT_FALSE(Params.CollisionParticleFraction == 1.0f); // not defaulted
2021-08-26 06:58:14 -04:00
}
2020-05-05 11:41:40 -04:00
}
2021-08-26 06:58:36 -04:00
2020-05-05 11:41:40 -04:00
}
2021-08-26 06:58:14 -04:00
2020-05-05 11:41:40 -04:00
}