Files
UnrealEngine/Engine/Source/Programs/HeadlessChaos/Private/GeometryCollection/GeometryCollectionTestBoneHierarchy.cpp
2025-05-18 13:04:45 +08:00

146 lines
4.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "GeometryCollection/GeometryCollectionTestBoneHierarchy.h"
#include "PhysicsProxy/AnalyticImplicitGroup.h"
#include "BoneHierarchy.h"
#include "Chaos/Sphere.h"
namespace GeometryCollectionTest
{
template <class TImplicitShape>
void AllOnSurface(const TImplicitShape *Shape, const TArray<Chaos::FVec3> &Points, const Chaos::FReal Tolerance = KINDA_SMALL_NUMBER)
{
for (auto &Pt : Points)
{
const Chaos::FReal Phi = Shape->SignedDistance(Pt);
EXPECT_NEAR(Phi, 0, Tolerance);
}
}
void TestSphere(const Chaos::FVec3& Center, const Chaos::FReal Radius, const FTransform &BoneRelXf)
{
Chaos::FSphere* Sphere = new Chaos::FSphere(Center, Radius);
TUniquePtr<FAnalyticImplicitGroup> Group1(new FAnalyticImplicitGroup("Root", 0));
Group1->Init(1);
Group1->SetParentBoneIndex(INDEX_NONE);
Group1->Add(BoneRelXf, Sphere);
const TArray<Chaos::FVec3> *Points = Group1->BuildSamplePoints(1.0, 1, 1000);
check(Points);
check(Points->Num());
Chaos::FImplicitObject *Implicit = Group1->BuildSimImplicitObject();
AllOnSurface(Implicit, *Points);
}
void TestSphere2(
const Chaos::FVec3& Center1,
const Chaos::FVec3& Center2,
const Chaos::FReal Radius1,
const Chaos::FReal Radius2,
const FTransform &BoneRelXf1,
const FTransform &BoneRelXf2)
{
Chaos::FSphere* Sphere1 = new Chaos::FSphere(Center1, Radius1);
Chaos::FSphere* Sphere2 = new Chaos::FSphere(Center2, Radius2);
TUniquePtr<FAnalyticImplicitGroup> Group1(new FAnalyticImplicitGroup("Root", 0));
Group1->Init(2);
Group1->SetParentBoneIndex(INDEX_NONE);
Group1->Add(BoneRelXf1, Sphere1);
Group1->Add(BoneRelXf2, Sphere2);
const TArray<Chaos::FVec3> *Points = Group1->BuildSamplePoints(1.0, 1, 1000);
check(Points);
check(Points->Num());
Chaos::FImplicitObject *Implicit = Group1->BuildSimImplicitObject();
AllOnSurface(Implicit, *Points);
}
void RunAnalyticImplicitGroupTest()
{
TestSphere(Chaos::FVec3(0, 0, 0), 1.0, FTransform::Identity);
TestSphere(Chaos::FVec3(0, 0, 0), 1.0, FTransform(FVector(1,0,0)));
TestSphere(Chaos::FVec3(0, 0, 0), 1.0, FTransform(FVector(1,1,0)));
TestSphere(Chaos::FVec3(0, 0, 0), 1.0, FTransform(FVector(1,1,1)));
//This test fails in Dev-Physics for spheres of larger radii
//TestSphere(R, Chaos::FVec3(0, 0, 0), 10.0, FTransform::Identity);
//TestSphere(R, Chaos::FVec3(0, 0, 0), 10.0, FTransform(FVector(1,0,0)));
//TestSphere(R, Chaos::FVec3(0, 0, 0), 10.0, FTransform(FVector(1,1,0)));
//TestSphere(R, Chaos::FVec3(0, 0, 0), 10.0, FTransform(FVector(1,1,1)));
TestSphere2(
Chaos::FVec3(0, 0, 0),
Chaos::FVec3(0, 0, 0),
1.0,
1.0,
FTransform(FVector(-2,0,0)),
FTransform(FVector(2,0,0)));
}
void RunBoneHierarchyTest()
{
FBoneHierarchy Hierarchy;
Hierarchy.InitPreAdd(2);
{
TUniquePtr<FAnalyticImplicitGroup> Group1(
new FAnalyticImplicitGroup("Root", 0));
Group1->SetParentBoneIndex(INDEX_NONE);
Group1->Add(FTransform::Identity, new Chaos::FSphere(Chaos::FVec3(0), 1.));
Hierarchy.Add(MoveTemp(Group1));
TUniquePtr<FAnalyticImplicitGroup> Group2(
new FAnalyticImplicitGroup("Bone1", 1));
Group2->SetParentBoneIndex(0);
Group2->Add(FTransform::Identity, new Chaos::FSphere(Chaos::FVec3(0), 1.));
Hierarchy.Add(MoveTemp(Group2));
Hierarchy.InitPostAdd();
}
Hierarchy.PrepareForUpdate();
Hierarchy.SetAnimLocalSpaceTransform(0,
FTransform(FQuat::MakeFromEuler(FVector(0, 0, 0)),
FVector(1,0,0)));
Hierarchy.SetAnimLocalSpaceTransform(1,
FTransform(FQuat::MakeFromEuler(FVector(0, 0, 0)),
FVector(0,1,0)));
Hierarchy.SetActorWorldSpaceTransform(
FTransform(FQuat::MakeFromEuler(FVector(0, 0, 0)),
FVector(0,0,1)));
Hierarchy.PrepareAnimWorldSpaceTransforms();
{
const FTransform* Xf = Hierarchy.GetAnimWorldSpaceTransformsForBone(1);
check(Xf);
const FTransform XfExpected(
FQuat::MakeFromEuler(FVector(0, 0, 0)),
FVector(1, 1, 1));
check(Xf->Equals(XfExpected));
}
Hierarchy.PrepareForUpdate();
Hierarchy.SetAnimLocalSpaceTransform(0,
FTransform(FQuat::MakeFromEuler(FVector(10, 0, 0)),
FVector(0,0,0)));
Hierarchy.SetAnimLocalSpaceTransform(1,
FTransform(FQuat::MakeFromEuler(FVector(10, 0, 0)),
FVector(0,0,0)));
Hierarchy.SetActorWorldSpaceTransform(
FTransform(FQuat::MakeFromEuler(FVector(10, 0, 0)),
FVector(0,0,0)));
Hierarchy.PrepareAnimWorldSpaceTransforms();
{
const FTransform* Xf = Hierarchy.GetAnimWorldSpaceTransformsForBone(1);
check(Xf);
const FTransform XfExpected(
FQuat::MakeFromEuler(FVector(30, 0, 0)),
FVector(0, 0, 0));
check(Xf->Equals(XfExpected));
}
}
void TestImplicitBoneHierarchy()
{
RunAnalyticImplicitGroupTest();
RunBoneHierarchyTest();
}
} // namespace GeometryCollectionTest