| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AZTestShared/Math/MathTestHelpers.h>
- #include <AzCore/Component/Entity.h>
- #include <AzFramework/Components/TransformComponent.h>
- #include <Components/ClothComponentMesh/ActorClothSkinning.h>
- #include <Utils/AssetHelper.h>
- #include <UnitTestHelper.h>
- #include <ActorHelper.h>
- #include <Integration/Components/ActorComponent.h>
- namespace UnitTest
- {
- //! Fixture to setup entity with actor component and the tests data.
- class NvClothActorClothSkinning
- : public ::testing::Test
- {
- public:
- const AZStd::string MeshNodeName = "cloth_mesh_node";
- const AZStd::vector<AZ::Vector3> MeshVertices = {{
- AZ::Vector3(-1.0f, 0.0f, 0.0f),
- AZ::Vector3(1.0f, 0.0f, 0.0f),
- AZ::Vector3(0.0f, 1.0f, 0.0f)
- }};
- const AZStd::vector<NvCloth::SimParticleFormat> MeshParticles = {{
- NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[0], 1.0f),
- NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[1], 1.0f),
- NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[2], 1.0f),
- }};
-
- const AZStd::vector<NvCloth::SimIndexType> MeshIndices = {{
- 0, 1, 2
- }};
-
- const AZStd::vector<VertexSkinInfluences> MeshSkinningInfo = {{
- { {0, 1.0f} },
- { {0, 1.0f} },
- { {0, 1.0f} },
- }};
- const AZStd::vector<int> MeshRemappedVertices = {{
- 0, 1, 2
- }};
- const AZ::u32 LodLevel = 0;
- const NvCloth::MeshNodeInfo MeshNodeInfo = {
- static_cast<int>(LodLevel),
- {{
- // One SubMesh
- {
- 0, // Primitive index
- 0, // First vertex
- static_cast<int>(MeshVertices.size()), // Vertex count
- 0, // First index
- static_cast<int>(MeshIndices.size()) // Index count
- }
- }}
- };
- protected:
- // ::testing::Test overrides ...
- void SetUp() override;
- void TearDown() override;
- EMotionFX::Integration::ActorComponent* m_actorComponent = nullptr;
- private:
- AZStd::unique_ptr<AZ::Entity> m_entity;
- };
- void NvClothActorClothSkinning::SetUp()
- {
- m_entity = AZStd::make_unique<AZ::Entity>();
- m_entity->CreateComponent<AzFramework::TransformComponent>();
- m_actorComponent = m_entity->CreateComponent<EMotionFX::Integration::ActorComponent>();
- m_entity->Init();
- m_entity->Activate();
- }
- void NvClothActorClothSkinning::TearDown()
- {
- m_entity->Deactivate();
- m_actorComponent = nullptr;
- m_entity.reset();
- }
- TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithNoData_ReturnsNull)
- {
- AZ::EntityId entityId;
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(entityId, {}, {}, 0, {});
- EXPECT_TRUE(actorClothSkinning.get() == nullptr);
- }
- TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithDataButWithInvalidEntityId_ReturnsNull)
- {
- AZ::EntityId entityId;
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
- EXPECT_TRUE(actorClothSkinning.get() == nullptr);
- }
- TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithEmptyActor_ReturnsNull)
- {
- {
- auto actor = AZStd::make_unique<ActorHelper>("actor_test");
- actor->FinishSetup();
- m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
- }
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), {}, {}, 0, {});
- EXPECT_TRUE(actorClothSkinning.get() == nullptr);
- }
- TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithActorWhoseMeshHasNoSkinningInfo_ReturnsNull)
- {
- {
- auto actor = AZStd::make_unique<ActorHelper>("actor_test");
- auto meshNodeIndex = actor->AddJoint(MeshNodeName);
- actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices));
- actor->FinishSetup();
- m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
- }
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
- EXPECT_TRUE(actorClothSkinning.get() == nullptr);
- }
- TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_CreateWithActor_ReturnsValidInstance)
- {
- {
- auto actor = AZStd::make_unique<ActorHelper>("actor_test");
- auto meshNodeIndex = actor->AddJoint(MeshNodeName);
- actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo));
- actor->FinishSetup();
- m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
- }
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
- EXPECT_TRUE(actorClothSkinning.get() != nullptr);
- }
- TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateAndApplyLinearSkinning_ModifiesVertices)
- {
- const AZ::Transform meshNodeTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
- EMotionFX::Integration::ActorComponent::Configuration actorConfig;
- actorConfig.m_skinningMethod = EMotionFX::Integration::SkinningMethod::Linear;
- auto entity = AZStd::make_unique<AZ::Entity>();
- entity->CreateComponent<AzFramework::TransformComponent>();
- auto* actorComponent = entity->CreateComponent<EMotionFX::Integration::ActorComponent>(&actorConfig);
- entity->Init();
- entity->Activate();
- {
- auto actor = AZStd::make_unique<ActorHelper>("actor_test");
- auto meshNodeIndex = actor->AddJoint(MeshNodeName, meshNodeTransform);
- actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo));
- actor->FinishSetup();
- actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
- }
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
- ASSERT_TRUE(actorClothSkinning.get() != nullptr);
- AZStd::vector<NvCloth::SimParticleFormat> skinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
- actorClothSkinning->UpdateSkinning();
- actorClothSkinning->ApplySkinning(MeshParticles, skinnedClothParticles);
- EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), MeshParticles));
- // Update actor instance's joints transforms
- const AZ::Transform newMeshNodeTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(180.0f));
- EMotionFX::Pose* currentPose = actorComponent->GetActorInstance()->GetTransformData()->GetCurrentPose();
- currentPose->SetLocalSpaceTransform(0, newMeshNodeTransform);
- actorComponent->GetActorInstance()->UpdateSkinningMatrices();
- AZStd::vector<NvCloth::SimParticleFormat> newSkinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
- actorClothSkinning->UpdateSkinning();
- actorClothSkinning->ApplySkinning(MeshParticles, newSkinnedClothParticles);
- const AZ::Transform diffTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
- const AZStd::vector<NvCloth::SimParticleFormat> clothParticlesResult = {{
- NvCloth::SimParticleFormat::CreateFromVector3AndFloat(diffTransform.TransformPoint(MeshVertices[0]), 1.0f),
- NvCloth::SimParticleFormat::CreateFromVector3AndFloat(diffTransform.TransformPoint(MeshVertices[1]), 1.0f),
- NvCloth::SimParticleFormat::CreateFromVector3AndFloat(diffTransform.TransformPoint(MeshVertices[2]), 1.0f),
- }};
- EXPECT_THAT(newSkinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticlesResult));
- }
- TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateAndApplyDualQuatSkinning_ModifiesVertices)
- {
- const AZStd::string rootNodeName = "root_node";
- const AZStd::string meshNodeName = "cloth_mesh_node";
-
- const AZStd::vector<VertexSkinInfluences> meshSkinningInfo = {{
- { {1, 0.75f}, {0, 0.25f} },
- { {1, 0.75f}, {0, 0.25f} },
- { {1, 0.75f}, {0, 0.25f} },
- }};
- const AZ::Transform rootNodeTransform = AZ::Transform::CreateTranslation(AZ::Vector3(2.0f, 53.0f, -65.0f));
- const AZ::Transform meshNodeTransform = AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateRotationY(AZ::DegToRad(36.0f)), AZ::Vector3(3.0f, -2.3f, 16.0f));
- {
- auto actor = AZStd::make_unique<ActorHelper>("actor_test");
- actor->AddJoint(rootNodeName, rootNodeTransform);
- auto meshNodeIndex = actor->AddJoint(meshNodeName, meshNodeTransform, rootNodeName);
- actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, meshSkinningInfo));
- actor->FinishSetup();
- m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
- }
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
- ASSERT_TRUE(actorClothSkinning.get() != nullptr);
-
- AZStd::vector<NvCloth::SimParticleFormat> skinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
- actorClothSkinning->UpdateSkinning();
- actorClothSkinning->ApplySkinning(MeshParticles, skinnedClothParticles);
- EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), MeshParticles));
- // Update actor instance's joints transforms
- const AZ::Transform newJointRootTransform = AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateRotationZ(AZ::DegToRad(-32.0f)), AZ::Vector3(2.5f, -6.0f, 0.2f));
- const AZ::Transform newJointChildTransform = AZ::Transform::CreateTranslation(AZ::Vector3(-2.0f, 3.0f, 0.0f));
- EMotionFX::Pose* currentPose = m_actorComponent->GetActorInstance()->GetTransformData()->GetCurrentPose();
- currentPose->SetLocalSpaceTransform(0, newJointRootTransform);
- currentPose->SetLocalSpaceTransform(1, newJointChildTransform);
- m_actorComponent->GetActorInstance()->UpdateSkinningMatrices();
- AZStd::vector<NvCloth::SimParticleFormat> newSkinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
- actorClothSkinning->UpdateSkinning();
- actorClothSkinning->ApplySkinning(MeshParticles, newSkinnedClothParticles);
- const AZStd::vector<NvCloth::SimParticleFormat> clothParticlesResult = {{
- NvCloth::SimParticleFormat(-48.4177f, -31.9446f, 45.2279f, 1.0f),
- NvCloth::SimParticleFormat(-46.9087f, -32.8876f, 46.1409f, 1.0f),
- NvCloth::SimParticleFormat(-47.1333f, -31.568f, 45.6844f, 1.0f),
- }};
- EXPECT_THAT(newSkinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticlesResult));
- }
- TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateActorVisibility_ReturnsExpectedValues)
- {
- {
- auto actor = AZStd::make_unique<ActorHelper>("actor_test");
- auto meshNodeIndex = actor->AddJoint(MeshNodeName);
- actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo));
- actor->FinishSetup();
- m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
- }
- AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
- NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
- ASSERT_TRUE(actorClothSkinning.get() != nullptr);
- EXPECT_FALSE(actorClothSkinning->IsActorVisible());
- EXPECT_FALSE(actorClothSkinning->WasActorVisible());
- m_actorComponent->GetActorInstance()->SetIsVisible(true);
- actorClothSkinning->UpdateActorVisibility();
- EXPECT_TRUE(actorClothSkinning->IsActorVisible());
- EXPECT_FALSE(actorClothSkinning->WasActorVisible());
- actorClothSkinning->UpdateActorVisibility();
- EXPECT_TRUE(actorClothSkinning->IsActorVisible());
- EXPECT_TRUE(actorClothSkinning->WasActorVisible());
- m_actorComponent->GetActorInstance()->SetIsVisible(false);
- actorClothSkinning->UpdateActorVisibility();
- EXPECT_FALSE(actorClothSkinning->IsActorVisible());
- EXPECT_TRUE(actorClothSkinning->WasActorVisible());
- actorClothSkinning->UpdateActorVisibility();
- EXPECT_FALSE(actorClothSkinning->IsActorVisible());
- EXPECT_FALSE(actorClothSkinning->WasActorVisible());
- }
- } // namespace UnitTest
|