3
0

ActorClothSkinningTest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AZTestShared/Math/MathTestHelpers.h>
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzFramework/Components/TransformComponent.h>
  11. #include <Components/ClothComponentMesh/ActorClothSkinning.h>
  12. #include <Utils/AssetHelper.h>
  13. #include <UnitTestHelper.h>
  14. #include <ActorHelper.h>
  15. #include <Integration/Components/ActorComponent.h>
  16. namespace UnitTest
  17. {
  18. //! Fixture to setup entity with actor component and the tests data.
  19. class NvClothActorClothSkinning
  20. : public ::testing::Test
  21. {
  22. public:
  23. const AZStd::string MeshNodeName = "cloth_mesh_node";
  24. const AZStd::vector<AZ::Vector3> MeshVertices = {{
  25. AZ::Vector3(-1.0f, 0.0f, 0.0f),
  26. AZ::Vector3(1.0f, 0.0f, 0.0f),
  27. AZ::Vector3(0.0f, 1.0f, 0.0f)
  28. }};
  29. const AZStd::vector<NvCloth::SimParticleFormat> MeshParticles = {{
  30. NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[0], 1.0f),
  31. NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[1], 1.0f),
  32. NvCloth::SimParticleFormat::CreateFromVector3AndFloat(MeshVertices[2], 1.0f),
  33. }};
  34. const AZStd::vector<NvCloth::SimIndexType> MeshIndices = {{
  35. 0, 1, 2
  36. }};
  37. const AZStd::vector<VertexSkinInfluences> MeshSkinningInfo = {{
  38. { {0, 1.0f} },
  39. { {0, 1.0f} },
  40. { {0, 1.0f} },
  41. }};
  42. const AZStd::vector<int> MeshRemappedVertices = {{
  43. 0, 1, 2
  44. }};
  45. const AZ::u32 LodLevel = 0;
  46. const NvCloth::MeshNodeInfo MeshNodeInfo = {
  47. static_cast<int>(LodLevel),
  48. {{
  49. // One SubMesh
  50. {
  51. 0, // Primitive index
  52. 0, // First vertex
  53. static_cast<int>(MeshVertices.size()), // Vertex count
  54. 0, // First index
  55. static_cast<int>(MeshIndices.size()) // Index count
  56. }
  57. }}
  58. };
  59. protected:
  60. // ::testing::Test overrides ...
  61. void SetUp() override;
  62. void TearDown() override;
  63. EMotionFX::Integration::ActorComponent* m_actorComponent = nullptr;
  64. private:
  65. AZStd::unique_ptr<AZ::Entity> m_entity;
  66. };
  67. void NvClothActorClothSkinning::SetUp()
  68. {
  69. m_entity = AZStd::make_unique<AZ::Entity>();
  70. m_entity->CreateComponent<AzFramework::TransformComponent>();
  71. m_actorComponent = m_entity->CreateComponent<EMotionFX::Integration::ActorComponent>();
  72. m_entity->Init();
  73. m_entity->Activate();
  74. }
  75. void NvClothActorClothSkinning::TearDown()
  76. {
  77. m_entity->Deactivate();
  78. m_actorComponent = nullptr;
  79. m_entity.reset();
  80. }
  81. TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithNoData_ReturnsNull)
  82. {
  83. AZ::EntityId entityId;
  84. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  85. NvCloth::ActorClothSkinning::Create(entityId, {}, {}, 0, {});
  86. EXPECT_TRUE(actorClothSkinning.get() == nullptr);
  87. }
  88. TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithDataButWithInvalidEntityId_ReturnsNull)
  89. {
  90. AZ::EntityId entityId;
  91. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  92. NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
  93. EXPECT_TRUE(actorClothSkinning.get() == nullptr);
  94. }
  95. TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithEmptyActor_ReturnsNull)
  96. {
  97. {
  98. auto actor = AZStd::make_unique<ActorHelper>("actor_test");
  99. actor->FinishSetup();
  100. m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
  101. }
  102. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  103. NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), {}, {}, 0, {});
  104. EXPECT_TRUE(actorClothSkinning.get() == nullptr);
  105. }
  106. TEST_F(NvClothActorClothSkinning, ActorClothSkinning_CreateWithActorWhoseMeshHasNoSkinningInfo_ReturnsNull)
  107. {
  108. {
  109. auto actor = AZStd::make_unique<ActorHelper>("actor_test");
  110. auto meshNodeIndex = actor->AddJoint(MeshNodeName);
  111. actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices));
  112. actor->FinishSetup();
  113. m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
  114. }
  115. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  116. NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
  117. EXPECT_TRUE(actorClothSkinning.get() == nullptr);
  118. }
  119. TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_CreateWithActor_ReturnsValidInstance)
  120. {
  121. {
  122. auto actor = AZStd::make_unique<ActorHelper>("actor_test");
  123. auto meshNodeIndex = actor->AddJoint(MeshNodeName);
  124. actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo));
  125. actor->FinishSetup();
  126. m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
  127. }
  128. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  129. NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
  130. EXPECT_TRUE(actorClothSkinning.get() != nullptr);
  131. }
  132. TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateAndApplyLinearSkinning_ModifiesVertices)
  133. {
  134. const AZ::Transform meshNodeTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
  135. EMotionFX::Integration::ActorComponent::Configuration actorConfig;
  136. actorConfig.m_skinningMethod = EMotionFX::Integration::SkinningMethod::Linear;
  137. auto entity = AZStd::make_unique<AZ::Entity>();
  138. entity->CreateComponent<AzFramework::TransformComponent>();
  139. auto* actorComponent = entity->CreateComponent<EMotionFX::Integration::ActorComponent>(&actorConfig);
  140. entity->Init();
  141. entity->Activate();
  142. {
  143. auto actor = AZStd::make_unique<ActorHelper>("actor_test");
  144. auto meshNodeIndex = actor->AddJoint(MeshNodeName, meshNodeTransform);
  145. actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo));
  146. actor->FinishSetup();
  147. actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
  148. }
  149. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  150. NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
  151. ASSERT_TRUE(actorClothSkinning.get() != nullptr);
  152. AZStd::vector<NvCloth::SimParticleFormat> skinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
  153. actorClothSkinning->UpdateSkinning();
  154. actorClothSkinning->ApplySkinning(MeshParticles, skinnedClothParticles);
  155. EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), MeshParticles));
  156. // Update actor instance's joints transforms
  157. const AZ::Transform newMeshNodeTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(180.0f));
  158. EMotionFX::Pose* currentPose = actorComponent->GetActorInstance()->GetTransformData()->GetCurrentPose();
  159. currentPose->SetLocalSpaceTransform(0, newMeshNodeTransform);
  160. actorComponent->GetActorInstance()->UpdateSkinningMatrices();
  161. AZStd::vector<NvCloth::SimParticleFormat> newSkinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
  162. actorClothSkinning->UpdateSkinning();
  163. actorClothSkinning->ApplySkinning(MeshParticles, newSkinnedClothParticles);
  164. const AZ::Transform diffTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f));
  165. const AZStd::vector<NvCloth::SimParticleFormat> clothParticlesResult = {{
  166. NvCloth::SimParticleFormat::CreateFromVector3AndFloat(diffTransform.TransformPoint(MeshVertices[0]), 1.0f),
  167. NvCloth::SimParticleFormat::CreateFromVector3AndFloat(diffTransform.TransformPoint(MeshVertices[1]), 1.0f),
  168. NvCloth::SimParticleFormat::CreateFromVector3AndFloat(diffTransform.TransformPoint(MeshVertices[2]), 1.0f),
  169. }};
  170. EXPECT_THAT(newSkinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticlesResult));
  171. }
  172. TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateAndApplyDualQuatSkinning_ModifiesVertices)
  173. {
  174. const AZStd::string rootNodeName = "root_node";
  175. const AZStd::string meshNodeName = "cloth_mesh_node";
  176. const AZStd::vector<VertexSkinInfluences> meshSkinningInfo = {{
  177. { {1, 0.75f}, {0, 0.25f} },
  178. { {1, 0.75f}, {0, 0.25f} },
  179. { {1, 0.75f}, {0, 0.25f} },
  180. }};
  181. const AZ::Transform rootNodeTransform = AZ::Transform::CreateTranslation(AZ::Vector3(2.0f, 53.0f, -65.0f));
  182. const AZ::Transform meshNodeTransform = AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateRotationY(AZ::DegToRad(36.0f)), AZ::Vector3(3.0f, -2.3f, 16.0f));
  183. {
  184. auto actor = AZStd::make_unique<ActorHelper>("actor_test");
  185. actor->AddJoint(rootNodeName, rootNodeTransform);
  186. auto meshNodeIndex = actor->AddJoint(meshNodeName, meshNodeTransform, rootNodeName);
  187. actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, meshSkinningInfo));
  188. actor->FinishSetup();
  189. m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
  190. }
  191. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  192. NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
  193. ASSERT_TRUE(actorClothSkinning.get() != nullptr);
  194. AZStd::vector<NvCloth::SimParticleFormat> skinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
  195. actorClothSkinning->UpdateSkinning();
  196. actorClothSkinning->ApplySkinning(MeshParticles, skinnedClothParticles);
  197. EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), MeshParticles));
  198. // Update actor instance's joints transforms
  199. const AZ::Transform newJointRootTransform = AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateRotationZ(AZ::DegToRad(-32.0f)), AZ::Vector3(2.5f, -6.0f, 0.2f));
  200. const AZ::Transform newJointChildTransform = AZ::Transform::CreateTranslation(AZ::Vector3(-2.0f, 3.0f, 0.0f));
  201. EMotionFX::Pose* currentPose = m_actorComponent->GetActorInstance()->GetTransformData()->GetCurrentPose();
  202. currentPose->SetLocalSpaceTransform(0, newJointRootTransform);
  203. currentPose->SetLocalSpaceTransform(1, newJointChildTransform);
  204. m_actorComponent->GetActorInstance()->UpdateSkinningMatrices();
  205. AZStd::vector<NvCloth::SimParticleFormat> newSkinnedClothParticles(MeshParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f));
  206. actorClothSkinning->UpdateSkinning();
  207. actorClothSkinning->ApplySkinning(MeshParticles, newSkinnedClothParticles);
  208. const AZStd::vector<NvCloth::SimParticleFormat> clothParticlesResult = {{
  209. NvCloth::SimParticleFormat(-48.4177f, -31.9446f, 45.2279f, 1.0f),
  210. NvCloth::SimParticleFormat(-46.9087f, -32.8876f, 46.1409f, 1.0f),
  211. NvCloth::SimParticleFormat(-47.1333f, -31.568f, 45.6844f, 1.0f),
  212. }};
  213. EXPECT_THAT(newSkinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticlesResult));
  214. }
  215. TEST_F(NvClothActorClothSkinning, DISABLED_ActorClothSkinning_UpdateActorVisibility_ReturnsExpectedValues)
  216. {
  217. {
  218. auto actor = AZStd::make_unique<ActorHelper>("actor_test");
  219. auto meshNodeIndex = actor->AddJoint(MeshNodeName);
  220. actor->SetMesh(LodLevel, meshNodeIndex, CreateEMotionFXMesh(MeshVertices, MeshIndices, MeshSkinningInfo));
  221. actor->FinishSetup();
  222. m_actorComponent->SetActorAsset(CreateAssetFromActor(AZStd::move(actor)));
  223. }
  224. AZStd::unique_ptr<NvCloth::ActorClothSkinning> actorClothSkinning =
  225. NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshParticles, MeshParticles.size(), MeshRemappedVertices);
  226. ASSERT_TRUE(actorClothSkinning.get() != nullptr);
  227. EXPECT_FALSE(actorClothSkinning->IsActorVisible());
  228. EXPECT_FALSE(actorClothSkinning->WasActorVisible());
  229. m_actorComponent->GetActorInstance()->SetIsVisible(true);
  230. actorClothSkinning->UpdateActorVisibility();
  231. EXPECT_TRUE(actorClothSkinning->IsActorVisible());
  232. EXPECT_FALSE(actorClothSkinning->WasActorVisible());
  233. actorClothSkinning->UpdateActorVisibility();
  234. EXPECT_TRUE(actorClothSkinning->IsActorVisible());
  235. EXPECT_TRUE(actorClothSkinning->WasActorVisible());
  236. m_actorComponent->GetActorInstance()->SetIsVisible(false);
  237. actorClothSkinning->UpdateActorVisibility();
  238. EXPECT_FALSE(actorClothSkinning->IsActorVisible());
  239. EXPECT_TRUE(actorClothSkinning->WasActorVisible());
  240. actorClothSkinning->UpdateActorVisibility();
  241. EXPECT_FALSE(actorClothSkinning->IsActorVisible());
  242. EXPECT_FALSE(actorClothSkinning->WasActorVisible());
  243. }
  244. } // namespace UnitTest