3
0

ClothConstraintsTest.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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 <AzTest/AzTest.h>
  9. #include <Components/ClothComponentMesh/ClothConstraints.h>
  10. #include <UnitTestHelper.h>
  11. namespace UnitTest
  12. {
  13. //! Fixture to hold the tests data.
  14. class NvClothConstraints
  15. : public ::testing::Test
  16. {
  17. public:
  18. const AZStd::vector<float> MeshMotionConstraintsData = {{
  19. 1.0f, 0.5f, 0.0f
  20. }};
  21. const float MotionConstraintsMaxDistance = 3.0f;
  22. const AZStd::vector<AZ::Vector2> MeshBackstopOffsetAndRadiusData = {{
  23. AZ::Vector2(1.0f, 1.0f),
  24. AZ::Vector2(0.0f, 0.5f),
  25. AZ::Vector2(-1.0f, 0.1f)
  26. }};
  27. const float BackstopMaxRadius = 3.0f;
  28. const float BackstopMaxBackOffset = 2.0f;
  29. const float BackstopMaxFrontOffset = 5.0f;
  30. const AZStd::vector<int> MeshRemappedVertices = {{
  31. 0, 1, 2
  32. }};
  33. const AZStd::vector<NvCloth::SimParticleFormat> SimulationParticles = {{
  34. NvCloth::SimParticleFormat(1.0f,0.0f,0.0f,1.0f),
  35. NvCloth::SimParticleFormat(0.0f,1.0f,0.0f,0.0f),
  36. NvCloth::SimParticleFormat(0.0f,0.0f,1.0f,1.0f),
  37. }};
  38. const AZStd::vector<NvCloth::SimIndexType> SimulationIndices = {{
  39. 0, 1, 2
  40. }};
  41. };
  42. TEST_F(NvClothConstraints, ClothConstraints_DefaultConstruct_ReturnsEmptyData)
  43. {
  44. NvCloth::ClothConstraints clothConstraints;
  45. EXPECT_TRUE(clothConstraints.GetMotionConstraints().empty());
  46. EXPECT_TRUE(clothConstraints.GetSeparationConstraints().empty());
  47. clothConstraints.CalculateConstraints({}, {});
  48. EXPECT_TRUE(clothConstraints.GetMotionConstraints().empty());
  49. EXPECT_TRUE(clothConstraints.GetSeparationConstraints().empty());
  50. clothConstraints.CalculateConstraints(SimulationParticles, SimulationIndices);
  51. EXPECT_TRUE(clothConstraints.GetMotionConstraints().empty());
  52. EXPECT_TRUE(clothConstraints.GetSeparationConstraints().empty());
  53. }
  54. TEST_F(NvClothConstraints, ClothConstraints_CreateWithNoInfo_ReturnsEmptyData)
  55. {
  56. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  57. {},
  58. 0.0f,
  59. {},
  60. 0.0f,
  61. 0.0f,
  62. 0.0f,
  63. {},
  64. {},
  65. {});
  66. EXPECT_TRUE(clothConstraints->GetMotionConstraints().empty());
  67. EXPECT_TRUE(clothConstraints->GetSeparationConstraints().empty());
  68. }
  69. TEST_F(NvClothConstraints, ClothConstraints_CreateWithMotionConstraintsInfo_ReturnsValidMotionConstraints)
  70. {
  71. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  72. MeshMotionConstraintsData,
  73. MotionConstraintsMaxDistance,
  74. {},
  75. 0.0f,
  76. 0.0f,
  77. 0.0f,
  78. SimulationParticles,
  79. SimulationIndices,
  80. MeshRemappedVertices);
  81. const AZStd::vector<AZ::Vector4>& motionConstraints = clothConstraints->GetMotionConstraints();
  82. EXPECT_TRUE(motionConstraints.size() == SimulationParticles.size());
  83. EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(SimulationParticles[0].GetAsVector3(), Tolerance));
  84. EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(SimulationParticles[1].GetAsVector3(), Tolerance));
  85. EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(SimulationParticles[2].GetAsVector3(), Tolerance));
  86. EXPECT_NEAR(motionConstraints[0].GetW(), 3.0f, Tolerance);
  87. EXPECT_NEAR(motionConstraints[1].GetW(), 0.0f, Tolerance);
  88. EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance);
  89. }
  90. TEST_F(NvClothConstraints, ClothConstraints_SetMotionConstraintMaxDistance_UpdatesMotionsConstraints)
  91. {
  92. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  93. MeshMotionConstraintsData,
  94. MotionConstraintsMaxDistance,
  95. {},
  96. 0.0f,
  97. 0.0f,
  98. 0.0f,
  99. SimulationParticles,
  100. SimulationIndices,
  101. MeshRemappedVertices);
  102. const float newMotionConstraintsMaxDistance = 6.0f;
  103. clothConstraints->SetMotionConstraintMaxDistance(newMotionConstraintsMaxDistance);
  104. const AZStd::vector<AZ::Vector4>& motionConstraints = clothConstraints->GetMotionConstraints();
  105. EXPECT_TRUE(motionConstraints.size() == SimulationParticles.size());
  106. EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(SimulationParticles[0].GetAsVector3(), Tolerance));
  107. EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(SimulationParticles[1].GetAsVector3(), Tolerance));
  108. EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(SimulationParticles[2].GetAsVector3(), Tolerance));
  109. EXPECT_NEAR(motionConstraints[0].GetW(), 6.0f, Tolerance);
  110. EXPECT_NEAR(motionConstraints[1].GetW(), 0.0f, Tolerance);
  111. EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance);
  112. }
  113. TEST_F(NvClothConstraints, ClothConstraints_CreateWithBackstopInfo_ReturnsValidSeparationConstraints)
  114. {
  115. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  116. {},
  117. 0.0f,
  118. MeshBackstopOffsetAndRadiusData,
  119. BackstopMaxRadius,
  120. BackstopMaxBackOffset,
  121. BackstopMaxFrontOffset,
  122. SimulationParticles,
  123. SimulationIndices,
  124. MeshRemappedVertices);
  125. const AZStd::vector<AZ::Vector4>& separationConstraints = clothConstraints->GetSeparationConstraints();
  126. EXPECT_TRUE(separationConstraints.size() == SimulationParticles.size());
  127. EXPECT_NEAR(separationConstraints[0].GetW(), 3.0f, Tolerance);
  128. EXPECT_NEAR(separationConstraints[1].GetW(), 1.5f, Tolerance);
  129. EXPECT_NEAR(separationConstraints[2].GetW(), 0.3f, Tolerance);
  130. EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-1.88675f, -2.88675f, -2.88675f), Tolerance));
  131. EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-0.866025f, 0.133975f, -0.866025f), Tolerance));
  132. EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(3.05996f, 3.05996f, 4.05996f), Tolerance));
  133. }
  134. TEST_F(NvClothConstraints, ClothConstraints_SetBackstopMaxRadius_UpdatesSeparationConstraints)
  135. {
  136. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  137. {},
  138. 0.0f,
  139. MeshBackstopOffsetAndRadiusData,
  140. BackstopMaxRadius,
  141. BackstopMaxBackOffset,
  142. BackstopMaxFrontOffset,
  143. SimulationParticles,
  144. SimulationIndices,
  145. MeshRemappedVertices);
  146. const float newBackstopMaxRadius = 6.0f;
  147. clothConstraints->SetBackstopMaxRadius(newBackstopMaxRadius);
  148. const AZStd::vector<AZ::Vector4>& separationConstraints = clothConstraints->GetSeparationConstraints();
  149. EXPECT_TRUE(separationConstraints.size() == SimulationParticles.size());
  150. EXPECT_NEAR(separationConstraints[0].GetW(), 6.0f, Tolerance);
  151. EXPECT_NEAR(separationConstraints[1].GetW(), 3.0f, Tolerance);
  152. EXPECT_NEAR(separationConstraints[2].GetW(), 0.6f, Tolerance);
  153. EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-3.6188f, -4.6188f, -4.6188f), Tolerance));
  154. EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-1.73205f, -0.732051f, -1.73205f), Tolerance));
  155. EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(3.23316f, 3.23316f, 4.23316f), Tolerance));
  156. }
  157. TEST_F(NvClothConstraints, ClothConstraints_SetBackstopMaxOffsets_UpdatesSeparationConstraints)
  158. {
  159. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  160. {},
  161. 0.0f,
  162. MeshBackstopOffsetAndRadiusData,
  163. BackstopMaxRadius,
  164. BackstopMaxBackOffset,
  165. BackstopMaxFrontOffset,
  166. SimulationParticles,
  167. SimulationIndices,
  168. MeshRemappedVertices);
  169. const float newBackstopMaxBackOffset = -4.0f;
  170. const float newBackstopMaxFrontOffset = 3.0f;
  171. clothConstraints->SetBackstopMaxOffsets(newBackstopMaxBackOffset, newBackstopMaxFrontOffset);
  172. const AZStd::vector<AZ::Vector4>& separationConstraints = clothConstraints->GetSeparationConstraints();
  173. EXPECT_TRUE(separationConstraints.size() == SimulationParticles.size());
  174. EXPECT_NEAR(separationConstraints[0].GetW(), 3.0f, Tolerance);
  175. EXPECT_NEAR(separationConstraints[1].GetW(), 1.5f, Tolerance);
  176. EXPECT_NEAR(separationConstraints[2].GetW(), 0.3f, Tolerance);
  177. EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(5.04145f, 4.04145f, 4.04145f), Tolerance));
  178. EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(-0.866025f, 0.133975f, -0.866025f), Tolerance));
  179. EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(1.90526f, 1.90526f, 2.90526f), Tolerance));
  180. }
  181. TEST_F(NvClothConstraints, ClothConstraints_CalculateConstraintsWithEmptyData_ConstraintsRemainUnchanged)
  182. {
  183. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  184. MeshMotionConstraintsData,
  185. MotionConstraintsMaxDistance,
  186. MeshBackstopOffsetAndRadiusData,
  187. BackstopMaxRadius,
  188. BackstopMaxBackOffset,
  189. BackstopMaxFrontOffset,
  190. SimulationParticles,
  191. SimulationIndices,
  192. MeshRemappedVertices);
  193. const AZStd::vector<AZ::Vector4> motionConstraints = clothConstraints->GetMotionConstraints();
  194. const AZStd::vector<AZ::Vector4> separationConstraints = clothConstraints->GetSeparationConstraints();
  195. clothConstraints->CalculateConstraints({}, {});
  196. EXPECT_THAT(motionConstraints, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothConstraints->GetMotionConstraints()));
  197. EXPECT_THAT(separationConstraints, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothConstraints->GetSeparationConstraints()));
  198. }
  199. TEST_F(NvClothConstraints, ClothConstraints_CalculateConstraintsWithSameData_ConstraintsRemainUnchanged)
  200. {
  201. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  202. MeshMotionConstraintsData,
  203. MotionConstraintsMaxDistance,
  204. MeshBackstopOffsetAndRadiusData,
  205. BackstopMaxRadius,
  206. BackstopMaxBackOffset,
  207. BackstopMaxFrontOffset,
  208. SimulationParticles,
  209. SimulationIndices,
  210. MeshRemappedVertices);
  211. const AZStd::vector<AZ::Vector4> motionConstraints = clothConstraints->GetMotionConstraints();
  212. const AZStd::vector<AZ::Vector4> separationConstraints = clothConstraints->GetSeparationConstraints();
  213. clothConstraints->CalculateConstraints(SimulationParticles, SimulationIndices);
  214. EXPECT_THAT(motionConstraints, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothConstraints->GetMotionConstraints()));
  215. EXPECT_THAT(separationConstraints, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothConstraints->GetSeparationConstraints()));
  216. }
  217. TEST_F(NvClothConstraints, ClothConstraints_CalculateConstraintsWithNewParticles_ContraintsAreModified)
  218. {
  219. AZStd::unique_ptr<NvCloth::ClothConstraints> clothConstraints = NvCloth::ClothConstraints::Create(
  220. MeshMotionConstraintsData,
  221. MotionConstraintsMaxDistance,
  222. MeshBackstopOffsetAndRadiusData,
  223. BackstopMaxRadius,
  224. BackstopMaxBackOffset,
  225. BackstopMaxFrontOffset,
  226. SimulationParticles,
  227. SimulationIndices,
  228. MeshRemappedVertices);
  229. const AZStd::vector<NvCloth::SimParticleFormat> newParticles = {{
  230. NvCloth::SimParticleFormat(0.0f,0.0f,1.0f,1.0f),
  231. NvCloth::SimParticleFormat(0.0f,1.0f,0.0f,1.0f),
  232. NvCloth::SimParticleFormat(1.0f,0.0f,1.0f,0.0f),
  233. }};
  234. clothConstraints->CalculateConstraints(newParticles, SimulationIndices);
  235. const AZStd::vector<AZ::Vector4>& motionConstraints = clothConstraints->GetMotionConstraints();
  236. const AZStd::vector<AZ::Vector4>& separationConstraints = clothConstraints->GetSeparationConstraints();
  237. EXPECT_TRUE(motionConstraints.size() == newParticles.size());
  238. EXPECT_THAT(motionConstraints[0].GetAsVector3(), IsCloseTolerance(newParticles[0].GetAsVector3(), Tolerance));
  239. EXPECT_THAT(motionConstraints[1].GetAsVector3(), IsCloseTolerance(newParticles[1].GetAsVector3(), Tolerance));
  240. EXPECT_THAT(motionConstraints[2].GetAsVector3(), IsCloseTolerance(newParticles[2].GetAsVector3(), Tolerance));
  241. EXPECT_NEAR(motionConstraints[0].GetW(), 3.0f, Tolerance);
  242. EXPECT_NEAR(motionConstraints[1].GetW(), 1.5f, Tolerance);
  243. EXPECT_NEAR(motionConstraints[2].GetW(), 0.0f, Tolerance);
  244. EXPECT_TRUE(separationConstraints.size() == newParticles.size());
  245. EXPECT_NEAR(separationConstraints[0].GetW(), 3.0f, Tolerance);
  246. EXPECT_NEAR(separationConstraints[1].GetW(), 1.5f, Tolerance);
  247. EXPECT_NEAR(separationConstraints[2].GetW(), 0.3f, Tolerance);
  248. EXPECT_THAT(separationConstraints[0].GetAsVector3(), IsCloseTolerance(AZ::Vector3(0.0f, 3.53553f, 4.53553f), Tolerance));
  249. EXPECT_THAT(separationConstraints[1].GetAsVector3(), IsCloseTolerance(AZ::Vector3(0.0f, 2.06066f, 1.06066f), Tolerance));
  250. EXPECT_THAT(separationConstraints[2].GetAsVector3(), IsCloseTolerance(AZ::Vector3(1.0f, -3.74767f, -2.74767f), Tolerance));
  251. }
  252. } // namespace UnitTest