2020-05-05 11:41:40 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "GeometryCollection/GeometryCollectionTestCollisionResolution.h"
# include "GeometryCollection/GeometryCollectionTestFramework.h"
# include "GeometryCollection/GeometryCollectionAlgo.h"
# include "GeometryCollectionProxyData.h"
# include "HeadlessChaosTestUtility.h"
namespace GeometryCollectionTest
{
using namespace ChaosTest ;
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolutionTest )
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
FGeometryCollectionWrapper * Collection = nullptr ;
2020-05-05 11:41:40 -04:00
{
2020-10-09 22:42:26 -04:00
FVector GlobalTranslation ( 0 , 0 , 10 ) ;
FQuat GlobalRotation = FQuat : : MakeFromEuler ( FVector ( 0 ) ) ;
CreationParameters Params ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . EnableClustering = false ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . RootTransform = FTransform ( GlobalRotation , GlobalTranslation ) ;
Params . NestedTransforms = { FTransform : : Identity , FTransform : : Identity , FTransform : : Identity } ;
2021-03-18 15:20:03 -04:00
Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection - > DynamicCollection - > Parent [ 0 ] , 1 ) ; // is a child of index one
EXPECT_TRUE ( Collection - > DynamicCollection - > MassToLocal [ 0 ] . Equals ( FTransform : : Identity ) ) ; // we are not testing MassToLocal in this test
2020-10-09 22:42:26 -04:00
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
}
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 ) ;
UnitTest . Initialize ( ) ;
for ( int i = 0 ; i < 10000 ; i + + )
{
UnitTest . Advance ( ) ;
}
{
// validate that Simplicials are null when CollisionType==Chaos_Volumetric
EXPECT_EQ ( Collection - > DynamicCollection - > Transform . Num ( ) , 4 ) ;
EXPECT_EQ ( Collection - > DynamicCollection - > Simplicials [ 0 ] , nullptr ) ;
EXPECT_EQ ( Collection - > DynamicCollection - > Simplicials [ 1 ] , nullptr ) ;
EXPECT_EQ ( Collection - > DynamicCollection - > Simplicials [ 2 ] , nullptr ) ;
EXPECT_EQ ( Collection - > DynamicCollection - > Simplicials [ 3 ] , nullptr ) ;
EXPECT_EQ ( UnitTest . Solver - > GetParticles ( ) . GetGeometryCollectionParticles ( ) . CollisionParticles ( 0 ) , nullptr ) ;
2021-03-30 18:14:56 -04:00
const FReal MaxRestingSeparation = - UnitTest . Solver - > GetEvolution ( ) - > GetGravityForces ( ) . GetAcceleration ( ) . Z * UnitTest . Dt * UnitTest . Dt ; // PBD resting separation will be up to this
2020-05-05 11:41:40 -04:00
EXPECT_LT ( FMath : : Abs ( Collection - > RestCollection - > Transform [ 0 ] . GetTranslation ( ) . Z ) - 10.f , KINDA_SMALL_NUMBER ) ;
2021-03-30 18:14:56 -04:00
EXPECT_LT ( FMath : : Abs ( Collection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z - 1.0 ) , 0.1 + MaxRestingSeparation ) ;
2020-05-05 11:41:40 -04:00
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolution_SimplicialSphereToPlane )
2020-05-05 11:41:40 -04:00
{
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-09-01 14:07:48 -04:00
const FReal Radius = 100.0f ; // cm
2020-05-05 11:41:40 -04:00
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = nullptr ;
2020-05-05 11:41:40 -04:00
{
2020-09-01 14:07:48 -04:00
FVector GlobalTranslation ( 0 , 0 , Radius + 10 ) ; FQuat GlobalRotation = FQuat : : MakeFromEuler ( FVector ( 0 ) ) ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ; Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ; Params . EnableClustering = false ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ; Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ; Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . RootTransform = FTransform ( GlobalRotation , GlobalTranslation ) ; Params . NestedTransforms = { FTransform : : Identity , FTransform : : Identity , FTransform : : Identity } ;
2020-09-01 14:07:48 -04:00
FVector Scale ( Radius ) ;
Params . GeomTransform . SetScale3D ( Scale ) ; // Sphere radius
2021-03-18 15:20:03 -04:00
Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection - > DynamicCollection - > Parent [ 0 ] , 1 ) ; // is a child of index one
EXPECT_TRUE ( Collection - > DynamicCollection - > MassToLocal [ 0 ] . Equals ( FTransform : : Identity ) ) ; // we are not testing MassToLocal in this test
UnitTest . AddSimulationObject ( Collection ) ;
}
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 ) ;
UnitTest . Initialize ( ) ;
2020-09-01 14:07:48 -04:00
for ( int i = 0 ; i < 1000 ; i + + )
2020-05-05 11:41:40 -04:00
{
UnitTest . Advance ( ) ;
}
{
// validate that Simplicials are null when CollisionType==Chaos_Volumetric
EXPECT_EQ ( Collection - > DynamicCollection - > Transform . Num ( ) , 4 ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Simplicials [ 0 ] ! = nullptr ) ;
EXPECT_TRUE ( UnitTest . Solver - > GetParticles ( ) . GetGeometryCollectionParticles ( ) . CollisionParticles ( 0 ) ! = nullptr ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Simplicials [ 0 ] - > Size ( ) = = UnitTest . Solver - > GetParticles ( ) . GetGeometryCollectionParticles ( ) . CollisionParticles ( 0 ) - > Size ( ) ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Simplicials [ 0 ] - > Size ( ) ! = 0 ) ;
2020-09-01 14:07:48 -04:00
EXPECT_LT ( FMath : : Abs ( Collection - > RestCollection - > Transform [ 0 ] . GetTranslation ( ) . Z - ( Radius + 10.f ) ) , KINDA_SMALL_NUMBER ) ;
2022-01-14 19:02:17 -05:00
EXPECT_NEAR ( Collection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z , Radius , KINDA_SMALL_NUMBER ) ;
2020-05-05 11:41:40 -04:00
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolution_AnalyticSphereToAnalyticSphere )
2020-05-05 11:41:40 -04:00
{
// simplicial sphere to implicit sphere
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
Params . EnableClustering = false ;
FVector Scale ( 1.f ) ;
Params . GeomTransform . SetScale3D ( Scale ) ; // Sphere radius
Params . EnableClustering = false ;
// Make a dynamic simplicial sphere
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
//Params.ImplicitType = EImplicitTypeEnum::Chaos_Implicit_None; // Fails, falls right through
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . RootTransform =
FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 , 0 , 3.0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * SimplicialSphereCollection =
TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( SimplicialSphereCollection ) ;
// Make a kinematic implicit sphere
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
Params . RootTransform =
FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * ImplicitSphereCollection =
TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( ImplicitSphereCollection ) ;
// Hard code masstolocal on rest collection to identity
{
TManagedArray < FTransform > & MassToLocal =
2022-05-11 12:14:04 -04:00
SimplicialSphereCollection - > RestCollection - > template ModifyAttribute < FTransform > (
2020-05-05 11:41:40 -04:00
TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
{
TManagedArray < FTransform > & MassToLocal =
2022-05-11 12:14:04 -04:00
ImplicitSphereCollection - > RestCollection - > template ModifyAttribute < FTransform > (
2020-05-05 11:41:40 -04:00
TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
UnitTest . Initialize ( ) ;
EXPECT_EQ (
SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z ,
ImplicitSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z + 3 ) ;
const FVector FirstX = SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
FVector PrevX = FirstX ;
for ( int i = 0 ; i < 10 ; i + + )
{
UnitTest . Advance ( ) ;
const FVector & CurrX = SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_NE ( CurrX . Z , FirstX . Z ) ; // moved since init
2020-08-11 01:36:57 -04:00
EXPECT_GE ( PrevX . Z - CurrX . Z , - KINDA_SMALL_NUMBER ) ; // falling in -Z, or stopped
2020-05-05 11:41:40 -04:00
EXPECT_LE ( FMath : : Abs ( CurrX . X ) , KINDA_SMALL_NUMBER ) ; // straight down
EXPECT_LE ( FMath : : Abs ( CurrX . Y ) , KINDA_SMALL_NUMBER ) ; // straight down
PrevX = CurrX ;
}
{
// We expect the simplical sphere to drop by 0.1 in Z and come to rest
// on top of the implicit sphere.
const FVector & CurrX = SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_LE ( CurrX . Z - 2.0 , 0.2 ) ; // Relative large fudge factor accounts for aliasing?
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , DISABLED_GeometryCollection_CollisionResolution_AnalyticCubeToAnalyticCube )
2020-05-05 11:41:40 -04:00
{
// simplicial sphere to implicit sphere
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . EnableClustering = false ;
FVector Scale ( 1.f , 1.f , 1.f ) ;
Params . GeomTransform . SetScale3D ( Scale ) ; // Box dimensions
Params . EnableClustering = false ;
// Make a dynamic box
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Box ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
2020-06-23 18:40:00 -04:00
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
2020-05-05 11:41:40 -04:00
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . RootTransform = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 , 0 , 3.0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * BoxCollection0 =
TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( BoxCollection0 ) ;
// Make a kinematic box
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Box ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
2020-06-23 18:40:00 -04:00
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
2020-05-05 11:41:40 -04:00
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
Params . RootTransform = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * BoxCollection1 =
TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( BoxCollection1 ) ;
/*
// Hard code masstolocal on rest collection to identity
{
TManagedArray < FTransform > & MassToLocal =
BoxCollection0 - > RestCollection - > GetAttribute < FTransform > (
TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
{
TManagedArray < FTransform > & MassToLocal =
BoxCollection1 - > RestCollection - > GetAttribute < FTransform > (
TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
*/
UnitTest . Initialize ( ) ;
EXPECT_EQ (
BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z ,
BoxCollection1 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z + 3 ) ;
const FVector FirstX = BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
FVector PrevX = FirstX ;
for ( int i = 0 ; i < 10 ; i + + )
{
UnitTest . Advance ( ) ;
const FVector & CurrX = BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_NE ( CurrX . Z , FirstX . Z ) ; // moved since init
EXPECT_LE ( CurrX . Z , PrevX . Z ) ; // falling in -Z, or stopped
EXPECT_LE ( FMath : : Abs ( CurrX . X ) , KINDA_SMALL_NUMBER ) ; // No deflection
EXPECT_LE ( FMath : : Abs ( CurrX . Y ) , KINDA_SMALL_NUMBER ) ; // No deflection
PrevX = CurrX ;
}
{
// We expect the simplical sphere to drop by 0.1 in Z and come to rest
// on top of the implicit sphere.
const FVector & CurrX = BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_LE ( CurrX . Z - 2.0 , 0.2 ) ; // Relative large fudge factor accounts for aliasing?
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolution_SimplicialSphereToAnalyticSphere )
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
// This should exercise CollisionResolution::ConstructLevelsetLevelsetConstraints(...) with ispc:SampleSphere* (Paticle to Analytic Sphere)
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = nullptr ;
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
FVector GlobalTranslation ( 0 , 0 , 10 ) ;
FQuat GlobalRotation = FQuat : : MakeFromEuler ( FVector ( 0 ) ) ;
CreationParameters Params ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . EnableClustering = false ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
Params . RootTransform = FTransform ( GlobalRotation , GlobalTranslation ) ;
Params . NestedTransforms = { FTransform : : Identity , FTransform : : Identity , FTransform : : Identity } ;
2021-03-18 15:20:03 -04:00
Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-06-23 18:40:00 -04:00
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection - > DynamicCollection - > Parent [ 0 ] , 1 ) ; // is a child of index one
EXPECT_TRUE ( Collection - > DynamicCollection - > MassToLocal [ 0 ] . Equals ( FTransform : : Identity ) ) ; // we are not testing MassToLocal in this test
UnitTest . AddSimulationObject ( Collection ) ;
}
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * CollectionStaticSphere = nullptr ;
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
FVector GlobalTranslation ( 0 , 0 , 0 ) ;
FQuat GlobalRotation = FQuat : : MakeFromEuler ( FVector ( 0 ) ) ;
CreationParameters Params ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Static ;
Params . EnableClustering = false ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Volumetric ;
2020-05-05 11:41:40 -04:00
Params . RootTransform = FTransform ( GlobalRotation , GlobalTranslation ) ; Params . NestedTransforms = { FTransform : : Identity , FTransform : : Identity , FTransform : : Identity } ;
2021-03-18 15:20:03 -04:00
CollectionStaticSphere = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( CollectionStaticSphere - > DynamicCollection - > Parent [ 0 ] , 1 ) ; // is a child of index one
EXPECT_TRUE ( CollectionStaticSphere - > DynamicCollection - > MassToLocal [ 0 ] . Equals ( FTransform : : Identity ) ) ; // we are not testing MassToLocal in this test
UnitTest . AddSimulationObject ( CollectionStaticSphere ) ;
}
UnitTest . Initialize ( ) ;
for ( int i = 0 ; i < 20 ; i + + )
{
UnitTest . Advance ( ) ;
}
{
// validate simplicials and implicits are configured correctly
EXPECT_EQ ( Collection - > DynamicCollection - > Transform . Num ( ) , 4 ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Simplicials [ 0 ] ! = nullptr ) ;
EXPECT_TRUE ( UnitTest . Solver - > GetParticles ( ) . GetGeometryCollectionParticles ( ) . CollisionParticles ( 0 ) ! = nullptr ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Simplicials [ 0 ] - > Size ( ) = = UnitTest . Solver - > GetParticles ( ) . GetGeometryCollectionParticles ( ) . CollisionParticles ( 0 ) - > Size ( ) ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Simplicials [ 0 ] - > Size ( ) ! = 0 ) ;
EXPECT_TRUE ( Collection - > DynamicCollection - > Implicits [ 0 ] - > GetType ( ) = = ( int32 ) Chaos : : ImplicitObjectType : : LevelSet ) ;
EXPECT_EQ ( CollectionStaticSphere - > DynamicCollection - > Transform . Num ( ) , 4 ) ;
EXPECT_TRUE ( CollectionStaticSphere - > DynamicCollection - > Simplicials [ 0 ] = = nullptr ) ;
EXPECT_TRUE ( CollectionStaticSphere - > DynamicCollection - > Implicits [ 0 ] - > GetType ( ) = = ( int32 ) Chaos : : ImplicitObjectType : : Sphere ) ;
// validate the ball collides and moved away from the static ball
EXPECT_LT ( FMath : : Abs ( Collection - > RestCollection - > Transform [ 0 ] . GetTranslation ( ) . Z ) - 10.f , KINDA_SMALL_NUMBER ) ;
2020-08-11 01:36:57 -04:00
EXPECT_TRUE ( FMath : : Abs ( Collection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . X ) < 0.001 ) ; // No deflection
EXPECT_TRUE ( FMath : : Abs ( Collection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Y ) < 0.001 ) ; // No deflection
2020-09-01 14:07:48 -04:00
EXPECT_LT ( Collection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z , 2.1f ) ; // ball fell
2020-05-05 11:41:40 -04:00
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolution_SimplicialSphereToImplicitSphere )
2020-05-05 11:41:40 -04:00
{
2020-06-23 18:40:00 -04:00
2020-05-05 11:41:40 -04:00
// simplicial sphere to implicit sphere
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . EnableClustering = false ;
2020-09-01 14:07:48 -04:00
FReal Radius = 100.0f ;
FVector Scale ( Radius ) ;
2020-05-05 11:41:40 -04:00
Params . GeomTransform . SetScale3D ( Scale ) ; // Sphere radius
Params . EnableClustering = false ;
// Make a dynamic simplicial sphere
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Sphere ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
2020-09-01 14:07:48 -04:00
Params . RootTransform = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 , 0 , 2.0f * Radius + 1.0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * SimplicialSphereCollection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( SimplicialSphereCollection ) ;
// Make a kinematic implicit sphere
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Sphere ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
2020-06-23 18:40:00 -04:00
Params . RootTransform = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * ImplicitSphereCollection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( ImplicitSphereCollection ) ;
// Hard code masstolocal on rest collection to identity
{
2022-05-11 12:14:04 -04:00
TManagedArray < FTransform > & MassToLocal = SimplicialSphereCollection - > RestCollection - > template ModifyAttribute < FTransform > ( TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
2020-05-05 11:41:40 -04:00
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
{
2022-05-11 12:14:04 -04:00
TManagedArray < FTransform > & MassToLocal = ImplicitSphereCollection - > RestCollection - > template ModifyAttribute < FTransform > ( TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
2020-05-05 11:41:40 -04:00
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
UnitTest . Initialize ( ) ;
2020-09-01 14:07:48 -04:00
EXPECT_EQ ( SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z , ImplicitSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z + 2.0f * Radius + 1.0f ) ;
2020-05-05 11:41:40 -04:00
const FVector FirstX = SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
FVector PrevX = FirstX ;
for ( int i = 0 ; i < 10 ; i + + )
{
UnitTest . Advance ( ) ;
const FVector & CurrX = SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_NE ( CurrX . Z , FirstX . Z ) ; // moved since init
2020-06-23 18:40:00 -04:00
EXPECT_LE ( FMath : : Abs ( CurrX . X ) , 0.1f ) ; // straight down
EXPECT_LE ( FMath : : Abs ( CurrX . Y ) , 0.1f ) ; // straight down
2020-05-05 11:41:40 -04:00
PrevX = CurrX ;
}
{
// We expect the simplical sphere to drop by 0.1 in Z and come to rest
// on top of the implicit sphere.
const FVector & CurrX = SimplicialSphereCollection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
2020-09-01 14:07:48 -04:00
EXPECT_LE ( FMath : : Abs ( CurrX . Z - 2.0f * Radius ) , 0.1 * Radius ) ;
2020-05-05 11:41:40 -04:00
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolution_SimplicialCubeToImplicitCube )
2020-05-05 11:41:40 -04:00
{
// simplicial sphere to implicit sphere
2021-03-18 15:20:03 -04:00
FFramework UnitTest ;
2020-05-05 11:41:40 -04:00
CreationParameters Params ;
Params . EnableClustering = false ;
2020-09-01 14:07:48 -04:00
FReal Length = 100.0f ;
FVector Scale ( Length , Length , Length ) ;
2020-05-05 11:41:40 -04:00
Params . GeomTransform . SetScale3D ( Scale ) ; // Box dimensions
Params . EnableClustering = false ;
// Make a dynamic box
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Box ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_Box ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
2020-09-01 14:07:48 -04:00
Params . RootTransform = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 , 0 , Length + 2.0f ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * BoxCollection0 =
TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( BoxCollection0 ) ;
// Make a kinematic box
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Box ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Kinematic ;
Params . RootTransform = FTransform ( FQuat : : MakeFromEuler ( FVector ( 0 ) ) , FVector ( 0 ) ) ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * BoxCollection1 =
TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( BoxCollection1 ) ;
/*
// Hard code masstolocal on rest collection to identity
{
TManagedArray < FTransform > & MassToLocal =
BoxCollection0 - > RestCollection - > GetAttribute < FTransform > (
TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
{
TManagedArray < FTransform > & MassToLocal =
BoxCollection1 - > RestCollection - > GetAttribute < FTransform > (
TEXT ( " MassToLocal " ) , FTransformCollection : : TransformGroup ) ;
check ( MassToLocal . Num ( ) = = 1 ) ;
MassToLocal [ 0 ] = FTransform : : Identity ;
}
*/
UnitTest . Initialize ( ) ;
EXPECT_EQ (
BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z ,
2020-09-01 14:07:48 -04:00
BoxCollection1 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) . Z + Length + 2.0f ) ;
2020-05-05 11:41:40 -04:00
const FVector FirstX = BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
FVector PrevX = FirstX ;
for ( int i = 0 ; i < 10 ; i + + )
{
UnitTest . Advance ( ) ;
const FVector & CurrX = BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_NE ( CurrX . Z , FirstX . Z ) ; // moved since init
EXPECT_LE ( CurrX . Z , PrevX . Z ) ; // falling in -Z, or stopped
EXPECT_LE ( FMath : : Abs ( CurrX . X ) , KINDA_SMALL_NUMBER ) ; // straight down
EXPECT_LE ( FMath : : Abs ( CurrX . Y ) , KINDA_SMALL_NUMBER ) ; // straight down
PrevX = CurrX ;
}
{
2020-09-01 14:07:48 -04:00
// We expect the simplical cube to drop in Z direction and come to rest
// on top of the implicit cube.
2020-05-05 11:41:40 -04:00
const FVector & CurrX = BoxCollection0 - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
2020-09-01 14:07:48 -04:00
EXPECT_LE ( FMath : : Abs ( CurrX . Z - Length ) , 0.2 * Length ) ; // Relative large fudge factor accounts for spatial aliasing and contact location averaging.
2020-05-05 11:41:40 -04:00
}
}
2021-03-18 15:20:03 -04:00
GTEST_TEST ( AllTraits , GeometryCollection_CollisionResolution_SimplicialTetrahedronWithNonUniformMassToFloor )
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
2020-09-01 14:07:48 -04:00
FReal Scale = 100.0f ;
2021-03-18 15:20:03 -04:00
FGeometryCollectionWrapper * Collection = nullptr ;
2020-05-05 11:41:40 -04:00
{
2020-09-01 14:07:48 -04:00
FVector GlobalTranslation ( 0 , 0 , Scale + 10 ) ; FQuat GlobalRotation = FQuat : : MakeFromEuler ( FVector ( 0 ) ) ;
2020-10-29 13:38:15 -04:00
CreationParameters Params ;
Params . DynamicState = EObjectStateTypeEnum : : Chaos_Object_Dynamic ;
Params . EnableClustering = false ;
Params . ImplicitType = EImplicitTypeEnum : : Chaos_Implicit_LevelSet ;
Params . SimplicialType = ESimplicialType : : Chaos_Simplicial_Tetrahedron ;
Params . CollisionType = ECollisionTypeEnum : : Chaos_Surface_Volumetric ;
2020-05-05 11:41:40 -04:00
Params . GeomTransform = FTransform ( GlobalRotation , GlobalTranslation ) ;
2020-09-01 14:07:48 -04:00
FVector TetraHedronScale ( Scale ) ;
Params . GeomTransform . SetScale3D ( TetraHedronScale ) ; // Tetrahedron dimensions
2021-03-18 15:20:03 -04:00
Collection = TNewSimulationObject < GeometryType : : GeometryCollectionWithSingleRigid > : : Init ( Params ) - > template As < FGeometryCollectionWrapper > ( ) ;
2020-05-05 11:41:40 -04:00
EXPECT_EQ ( Collection - > DynamicCollection - > Parent [ 0 ] , - 1 ) ; // is a child of index one
2020-09-01 14:07:48 -04:00
EXPECT_NEAR ( ( Collection - > DynamicCollection - > MassToLocal [ 0 ] . GetTranslation ( ) - FVector ( 0 , 0 , Scale + 10 ) ) . Size ( ) , 0 , KINDA_SMALL_NUMBER ) ;
2020-05-05 11:41:40 -04:00
UnitTest . AddSimulationObject ( Collection ) ;
}
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 ) ;
UnitTest . Initialize ( ) ;
2020-12-11 14:21:20 -04:00
for ( int i = 0 ; i < 10 ; i + + )
2020-05-05 11:41:40 -04:00
{
UnitTest . Advance ( ) ;
}
{
2020-12-11 14:21:20 -04:00
// Expected resting distance depends on the collision solver implementation.
const FReal ExpectedRestingDistance = 0.0f ;
//const FReal ExpectedRestingDistance = UnitTest.Solver->GetEvolution()->GetGravityForces().GetAcceleration().Size() * UnitTest.Dt * UnitTest.Dt;
2020-10-22 19:19:16 -04:00
2020-12-11 14:21:20 -04:00
// The error in the resting distance depends on the number of pushout iterations, which is very low by default
2021-04-27 16:46:55 -04:00
// It also depends on whether manifolds are used for collision (no manifolds means larger errors)
const FReal RestingDistanceTolerance = 2.0f ;
2020-10-09 22:42:26 -04:00
2020-09-01 14:07:48 -04:00
// validate the tetahedron collides and moved away from the static floor
2020-10-29 13:38:15 -04:00
FVec3 RestTranslation = Collection - > RestCollection - > Transform [ 0 ] . GetTranslation ( ) ;
FVec3 DynamicTranslation = Collection - > DynamicCollection - > Transform [ 0 ] . GetTranslation ( ) ;
EXPECT_EQ ( RestTranslation . Z , 0.f ) ;
2020-12-11 14:21:20 -04:00
EXPECT_NEAR ( FMath : : Abs ( DynamicTranslation . X ) , 0.f , RestingDistanceTolerance ) ;
EXPECT_NEAR ( FMath : : Abs ( DynamicTranslation . Y ) , 0.f , RestingDistanceTolerance ) ;
EXPECT_NEAR ( DynamicTranslation . Z , - 10.f + ExpectedRestingDistance , RestingDistanceTolerance ) ;
2020-05-05 11:41:40 -04:00
}
}
} // namespace GeometryCollectionTest