TangentSpaceHelperTest.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  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/Interface/Interface.h>
  10. #include <AzCore/UnitTest/UnitTest.h>
  11. #include <AzCore/Math/Transform.h>
  12. #include <AzCore/Math/MathUtils.h>
  13. #include <UnitTestHelper.h>
  14. #include <TriangleInputHelper.h>
  15. #include <NvCloth/ITangentSpaceHelper.h>
  16. namespace UnitTest
  17. {
  18. TEST(NvClothSystem, TangentSpaceHelper_CalculateNormalsWithNoMesh_ReturnsEmptyNormals)
  19. {
  20. AZStd::vector<AZ::Vector3> normals;
  21. bool normalsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  22. {}, {},
  23. normals);
  24. EXPECT_TRUE(normalsCalculated);
  25. EXPECT_TRUE(normals.empty());
  26. }
  27. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsWithNoMesh_ReturnsEmptyTangentsAndBitangents)
  28. {
  29. AZStd::vector<AZ::Vector3> tangents;
  30. AZStd::vector<AZ::Vector3> bitangents;
  31. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  32. {}, {}, {}, {},
  33. tangents, bitangents);
  34. EXPECT_TRUE(tangentsCalculated);
  35. EXPECT_TRUE(tangents.empty());
  36. EXPECT_TRUE(bitangents.empty());
  37. }
  38. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpaceWithNoMesh_ReturnsEmptyTangentSpace)
  39. {
  40. AZStd::vector<AZ::Vector3> tangents;
  41. AZStd::vector<AZ::Vector3> bitangents;
  42. AZStd::vector<AZ::Vector3> normals;
  43. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  44. {}, {}, {},
  45. tangents, bitangents, normals);
  46. EXPECT_TRUE(tangentsCalculated);
  47. EXPECT_TRUE(tangents.empty());
  48. EXPECT_TRUE(bitangents.empty());
  49. EXPECT_TRUE(normals.empty());
  50. }
  51. TEST(NvClothSystem, TangentSpaceHelper_CalculateNormalsWithIncorrectIndices_ReturnsFalse)
  52. {
  53. const AZStd::vector<NvCloth::SimIndexType> incorrectIndices = { { 0, 1 } }; // Use incorrect number of indices for a triangle (multiple of 3)
  54. AZ_TEST_START_TRACE_SUPPRESSION;
  55. AZStd::vector<AZ::Vector3> normals;
  56. bool normalsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  57. {}, incorrectIndices,
  58. normals);
  59. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error
  60. EXPECT_FALSE(normalsCalculated);
  61. EXPECT_TRUE(normals.empty());
  62. }
  63. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsWithIncorrectIndices_ReturnsFalse)
  64. {
  65. const AZStd::vector<NvCloth::SimIndexType> incorrectIndices = { { 0, 1 } }; // Use incorrect number of indices for a triangle (multiple of 3)
  66. AZ_TEST_START_TRACE_SUPPRESSION;
  67. AZStd::vector<AZ::Vector3> tangents;
  68. AZStd::vector<AZ::Vector3> bitangents;
  69. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  70. {}, incorrectIndices, {}, {},
  71. tangents, bitangents);
  72. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error
  73. EXPECT_FALSE(tangentsCalculated);
  74. EXPECT_TRUE(tangents.empty());
  75. EXPECT_TRUE(bitangents.empty());
  76. }
  77. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpaceWithIncorrectIndices_ReturnsFalse)
  78. {
  79. const AZStd::vector<NvCloth::SimIndexType> incorrectIndices = { { 0, 1 } }; // Use incorrect number of indices for a triangle (multiple of 3)
  80. AZ_TEST_START_TRACE_SUPPRESSION;
  81. AZStd::vector<AZ::Vector3> tangents;
  82. AZStd::vector<AZ::Vector3> bitangents;
  83. AZStd::vector<AZ::Vector3> normals;
  84. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  85. {}, incorrectIndices, {},
  86. tangents, bitangents, normals);
  87. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error
  88. EXPECT_FALSE(tangentsCalculated);
  89. EXPECT_TRUE(tangents.empty());
  90. EXPECT_TRUE(bitangents.empty());
  91. EXPECT_TRUE(normals.empty());
  92. }
  93. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsWithIncorrectUVs_ReturnsFalse)
  94. {
  95. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  96. NvCloth::SimParticleFormat(-1.0f, 0.0f, 0.0f, 1.0f),
  97. NvCloth::SimParticleFormat(1.0f, 0.0f, 0.0f, 1.0f),
  98. NvCloth::SimParticleFormat(0.0f, 1.0f, 0.0f, 1.0f),
  99. }};
  100. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  101. const AZStd::vector<NvCloth::SimUVType> uvs = {{ // Wrong number of UVs, 2 instead of 3 like the number of vertices
  102. NvCloth::SimUVType(0.0f, 0.0f),
  103. NvCloth::SimUVType(1.0f, 0.0f)
  104. }};
  105. AZ_TEST_START_TRACE_SUPPRESSION;
  106. AZStd::vector<AZ::Vector3> tangents;
  107. AZStd::vector<AZ::Vector3> bitangents;
  108. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  109. vertices, indices, uvs, {},
  110. tangents, bitangents);
  111. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error
  112. EXPECT_FALSE(tangentsCalculated);
  113. EXPECT_TRUE(tangents.empty());
  114. EXPECT_TRUE(bitangents.empty());
  115. }
  116. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsWithIncorrectNormals_ReturnsFalse)
  117. {
  118. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  119. NvCloth::SimParticleFormat(-1.0f, 0.0f, 0.0f, 1.0f),
  120. NvCloth::SimParticleFormat(1.0f, 0.0f, 0.0f, 1.0f),
  121. NvCloth::SimParticleFormat(0.0f, 1.0f, 0.0f, 1.0f),
  122. }};
  123. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  124. const AZStd::vector<NvCloth::SimUVType> uvs = {{
  125. NvCloth::SimUVType(0.0f, 0.0f),
  126. NvCloth::SimUVType(1.0f, 0.0f),
  127. NvCloth::SimUVType(0.5f, 1.0f)
  128. }};
  129. // Wrong number of normals, 2 instead of 3 like the number of vertices
  130. const AZStd::vector<AZ::Vector3> normals = {{
  131. AZ::Vector3(0.0f, 0.0f, 1.0f),
  132. AZ::Vector3(0.0f, 0.0f, 1.0f)
  133. }};
  134. AZ_TEST_START_TRACE_SUPPRESSION;
  135. AZStd::vector<AZ::Vector3> tangents;
  136. AZStd::vector<AZ::Vector3> bitangents;
  137. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  138. vertices, indices, uvs, {},
  139. tangents, bitangents);
  140. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error
  141. EXPECT_FALSE(tangentsCalculated);
  142. EXPECT_TRUE(tangents.empty());
  143. EXPECT_TRUE(bitangents.empty());
  144. }
  145. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpaceWithIncorrectUVs_ReturnsFalse)
  146. {
  147. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  148. NvCloth::SimParticleFormat(-1.0f, 0.0f, 0.0f, 1.0f),
  149. NvCloth::SimParticleFormat(1.0f, 0.0f, 0.0f, 1.0f),
  150. NvCloth::SimParticleFormat(0.0f, 1.0f, 0.0f, 1.0f),
  151. }};
  152. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  153. const AZStd::vector<NvCloth::SimUVType> uvs = {{ // Wrong number of UVs, 2 instead of 3 like the number of vertices
  154. NvCloth::SimUVType(0.0f, 0.0f),
  155. NvCloth::SimUVType(1.0f, 0.0f)
  156. }};
  157. AZ_TEST_START_TRACE_SUPPRESSION;
  158. AZStd::vector<AZ::Vector3> tangents;
  159. AZStd::vector<AZ::Vector3> bitangents;
  160. AZStd::vector<AZ::Vector3> normals;
  161. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  162. vertices, indices, uvs,
  163. tangents, bitangents, normals);
  164. AZ_TEST_STOP_TRACE_SUPPRESSION(1); // Expect 1 error
  165. EXPECT_FALSE(tangentsCalculated);
  166. EXPECT_TRUE(tangents.empty());
  167. EXPECT_TRUE(bitangents.empty());
  168. EXPECT_TRUE(normals.empty());
  169. }
  170. TEST(NvClothSystem, TangentSpaceHelper_CalculateNormalsWithNoAreaTriangle_ReturnsFiniteNormals)
  171. {
  172. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  173. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  174. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  175. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  176. }};
  177. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  178. AZStd::vector<AZ::Vector3> normals;
  179. bool normalsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  180. vertices, indices,
  181. normals);
  182. EXPECT_TRUE(normalsCalculated);
  183. EXPECT_EQ(normals.size(), vertices.size());
  184. EXPECT_THAT(normals, ::testing::Each(IsFinite()));
  185. }
  186. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsWithNoAreaTriangle_ReturnsFiniteTangentsAndBitangents)
  187. {
  188. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  189. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  190. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  191. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  192. }};
  193. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  194. const AZStd::vector<NvCloth::SimUVType> uvs = {{
  195. NvCloth::SimUVType(0.0f, 0.0f),
  196. NvCloth::SimUVType(0.0f, 0.0f),
  197. NvCloth::SimUVType(0.0f, 0.0f)
  198. }};
  199. const AZStd::vector<AZ::Vector3> normals = {{
  200. AZ::Vector3(0.0f, 0.0f, 1.0f),
  201. AZ::Vector3(0.0f, 0.0f, 1.0f),
  202. AZ::Vector3(0.0f, 0.0f, 1.0f)
  203. }};
  204. AZStd::vector<AZ::Vector3> tangents;
  205. AZStd::vector<AZ::Vector3> bitangents;
  206. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  207. vertices, indices, uvs, normals,
  208. tangents, bitangents);
  209. EXPECT_TRUE(tangentsCalculated);
  210. EXPECT_EQ(tangents.size(), vertices.size());
  211. EXPECT_EQ(bitangents.size(), vertices.size());
  212. EXPECT_THAT(tangents, ::testing::Each(IsFinite()));
  213. EXPECT_THAT(bitangents, ::testing::Each(IsFinite()));
  214. }
  215. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpaceWithNoAreaTriangle_ReturnsFiniteTangentSpace)
  216. {
  217. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  218. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  219. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  220. NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f),
  221. }};
  222. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  223. const AZStd::vector<NvCloth::SimUVType> uvs = {{
  224. NvCloth::SimUVType(0.0f, 0.0f),
  225. NvCloth::SimUVType(0.0f, 0.0f),
  226. NvCloth::SimUVType(0.0f, 0.0f)
  227. }};
  228. AZStd::vector<AZ::Vector3> tangents;
  229. AZStd::vector<AZ::Vector3> bitangents;
  230. AZStd::vector<AZ::Vector3> normals;
  231. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  232. vertices, indices, uvs,
  233. tangents, bitangents, normals);
  234. EXPECT_TRUE(tangentsCalculated);
  235. EXPECT_EQ(tangents.size(), vertices.size());
  236. EXPECT_EQ(bitangents.size(), vertices.size());
  237. EXPECT_EQ(normals.size(), vertices.size());
  238. EXPECT_THAT(tangents, ::testing::Each(IsFinite()));
  239. EXPECT_THAT(bitangents, ::testing::Each(IsFinite()));
  240. EXPECT_THAT(normals, ::testing::Each(IsFinite()));
  241. }
  242. TEST(NvClothSystem, TangentSpaceHelper_CalculateNormalsWithNANVertices_ReturnsFiniteNormals)
  243. {
  244. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  245. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  246. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  247. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  248. }};
  249. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  250. AZStd::vector<AZ::Vector3> normals;
  251. bool normalsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  252. vertices, indices,
  253. normals);
  254. EXPECT_TRUE(normalsCalculated);
  255. EXPECT_EQ(normals.size(), vertices.size());
  256. EXPECT_THAT(normals, ::testing::Each(IsFinite()));
  257. }
  258. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsWithNANVertices_ReturnsFiniteTangentsAndBitangents)
  259. {
  260. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  261. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  262. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  263. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  264. }};
  265. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  266. const AZStd::vector<NvCloth::SimUVType> uvs = {{
  267. NvCloth::SimUVType(0.0f, 0.0f),
  268. NvCloth::SimUVType(0.0f, 0.0f),
  269. NvCloth::SimUVType(0.0f, 0.0f)
  270. }};
  271. const AZStd::vector<AZ::Vector3> normals = {{
  272. AZ::Vector3(0.0f, 0.0f, 1.0f),
  273. AZ::Vector3(0.0f, 0.0f, 1.0f),
  274. AZ::Vector3(0.0f, 0.0f, 1.0f)
  275. }};
  276. AZStd::vector<AZ::Vector3> tangents;
  277. AZStd::vector<AZ::Vector3> bitangents;
  278. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  279. vertices, indices, uvs, normals,
  280. tangents, bitangents);
  281. EXPECT_TRUE(tangentsCalculated);
  282. EXPECT_EQ(tangents.size(), vertices.size());
  283. EXPECT_EQ(bitangents.size(), vertices.size());
  284. EXPECT_THAT(tangents, ::testing::Each(IsFinite()));
  285. EXPECT_THAT(bitangents, ::testing::Each(IsFinite()));
  286. }
  287. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpaceWithNANVertices_ReturnsFiniteTangentSpace)
  288. {
  289. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  290. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  291. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  292. NvCloth::SimParticleFormat(std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::infinity(), 0.0f, 1.0f),
  293. }};
  294. const AZStd::vector<NvCloth::SimIndexType> indices = { {0, 1, 2} };
  295. const AZStd::vector<NvCloth::SimUVType> uvs = {{
  296. NvCloth::SimUVType(0.0f, 0.0f),
  297. NvCloth::SimUVType(0.0f, 0.0f),
  298. NvCloth::SimUVType(0.0f, 0.0f)
  299. }};
  300. AZStd::vector<AZ::Vector3> tangents;
  301. AZStd::vector<AZ::Vector3> bitangents;
  302. AZStd::vector<AZ::Vector3> normals;
  303. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  304. vertices, indices, uvs,
  305. tangents, bitangents, normals);
  306. EXPECT_TRUE(tangentsCalculated);
  307. EXPECT_EQ(tangents.size(), vertices.size());
  308. EXPECT_EQ(bitangents.size(), vertices.size());
  309. EXPECT_EQ(normals.size(), vertices.size());
  310. EXPECT_THAT(tangents, ::testing::Each(IsFinite()));
  311. EXPECT_THAT(bitangents, ::testing::Each(IsFinite()));
  312. EXPECT_THAT(normals, ::testing::Each(IsFinite()));
  313. }
  314. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpaceWithTriangle_ReturnsCorrectTangentSpace)
  315. {
  316. const AZStd::vector<NvCloth::SimParticleFormat> vertices = {{
  317. NvCloth::SimParticleFormat(-1.0f, 0.0f, 0.0f, 1.0f),
  318. NvCloth::SimParticleFormat(1.0f, 0.0f, 0.0f, 1.0f),
  319. NvCloth::SimParticleFormat(0.0f, 1.0f, 0.0f, 1.0f)
  320. }};
  321. const AZStd::vector<NvCloth::SimIndexType> indices = {{0, 1, 2}};
  322. const AZStd::vector<NvCloth::SimUVType> uvs = {{
  323. NvCloth::SimUVType(0.0f, 0.0f),
  324. NvCloth::SimUVType(1.0f, 0.0f),
  325. NvCloth::SimUVType(0.5f, 1.0f)
  326. }};
  327. AZStd::vector<AZ::Vector3> tangents;
  328. AZStd::vector<AZ::Vector3> bitangents;
  329. AZStd::vector<AZ::Vector3> normals;
  330. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  331. vertices, indices, uvs,
  332. tangents, bitangents, normals);
  333. EXPECT_TRUE(tangentsCalculated);
  334. EXPECT_THAT(tangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisX(), Tolerance)));
  335. EXPECT_THAT(bitangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisY(), Tolerance)));
  336. EXPECT_THAT(normals, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisZ(), Tolerance)));
  337. }
  338. TEST(NvClothSystem, TangentSpaceHelper_CalculateNormalsPlaneXY_ReturnsAxisZNomals)
  339. {
  340. const float width = 1.0f;
  341. const float height = 1.0f;
  342. const AZ::u32 segmentsX = 5;
  343. const AZ::u32 segmentsY = 5;
  344. const TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  345. const size_t numVertices = planeXY.m_vertices.size();
  346. AZStd::vector<AZ::Vector3> normals;
  347. bool normalsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  348. planeXY.m_vertices, planeXY.m_indices, normals);
  349. EXPECT_TRUE(normalsCalculated);
  350. EXPECT_EQ(normals.size(), numVertices);
  351. EXPECT_THAT(normals, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisZ(), Tolerance)));
  352. }
  353. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsPlaneXY_ReturnsAxisXTangentsAndAxisYBitangents)
  354. {
  355. const float width = 1.0f;
  356. const float height = 1.0f;
  357. const AZ::u32 segmentsX = 5;
  358. const AZ::u32 segmentsY = 5;
  359. const TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  360. const size_t numVertices = planeXY.m_vertices.size();
  361. AZStd::vector<AZ::Vector3> normals;
  362. AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  363. planeXY.m_vertices, planeXY.m_indices, normals);
  364. AZStd::vector<AZ::Vector3> tangents;
  365. AZStd::vector<AZ::Vector3> bitangents;
  366. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  367. planeXY.m_vertices, planeXY.m_indices, planeXY.m_uvs, normals,
  368. tangents, bitangents);
  369. EXPECT_TRUE(tangentsCalculated);
  370. EXPECT_EQ(tangents.size(), numVertices);
  371. EXPECT_EQ(bitangents.size(), numVertices);
  372. EXPECT_THAT(tangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisX(), Tolerance)));
  373. EXPECT_THAT(bitangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisY(), Tolerance)));
  374. }
  375. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpacePlaneXY_ReturnsCorrectTangentSpace)
  376. {
  377. const float width = 1.0f;
  378. const float height = 1.0f;
  379. const AZ::u32 segmentsX = 5;
  380. const AZ::u32 segmentsY = 5;
  381. const TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  382. const size_t numVertices = planeXY.m_vertices.size();
  383. AZStd::vector<AZ::Vector3> tangents;
  384. AZStd::vector<AZ::Vector3> bitangents;
  385. AZStd::vector<AZ::Vector3> normals;
  386. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  387. planeXY.m_vertices, planeXY.m_indices, planeXY.m_uvs,
  388. tangents, bitangents, normals);
  389. EXPECT_TRUE(tangentsCalculated);
  390. EXPECT_EQ(tangents.size(), numVertices);
  391. EXPECT_EQ(bitangents.size(), numVertices);
  392. EXPECT_EQ(normals.size(), numVertices);
  393. EXPECT_THAT(tangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisX(), Tolerance)));
  394. EXPECT_THAT(bitangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisY(), Tolerance)));
  395. EXPECT_THAT(normals, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisZ(), Tolerance)));
  396. }
  397. TEST(NvClothSystem, TangentSpaceHelper_CalculateNormalsPlaneXYRot90Y_ReturnsCorrectNormals)
  398. {
  399. const float width = 1.0f;
  400. const float height = 1.0f;
  401. const AZ::u32 segmentsX = 5;
  402. const AZ::u32 segmentsY = 5;
  403. TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  404. const size_t numVertices = planeXY.m_vertices.size();
  405. const AZ::Transform rotation90Y = AZ::Transform::CreateRotationY(AZ::Constants::HalfPi);
  406. for (auto& vertex : planeXY.m_vertices)
  407. {
  408. vertex.Set(
  409. rotation90Y.TransformPoint(vertex.GetAsVector3()),
  410. vertex.GetW()
  411. );
  412. }
  413. AZStd::vector<AZ::Vector3> normals;
  414. bool normalsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  415. planeXY.m_vertices, planeXY.m_indices, normals);
  416. EXPECT_TRUE(normalsCalculated);
  417. EXPECT_EQ(normals.size(), numVertices);
  418. EXPECT_THAT(normals, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisX(), Tolerance)));
  419. }
  420. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentsAndBitangentsPlaneXYRot90Y_ReturnsCorrectTangentsAndBitangents)
  421. {
  422. const float width = 1.0f;
  423. const float height = 1.0f;
  424. const AZ::u32 segmentsX = 5;
  425. const AZ::u32 segmentsY = 5;
  426. TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  427. const size_t numVertices = planeXY.m_vertices.size();
  428. const AZ::Transform rotation90Y = AZ::Transform::CreateRotationY(AZ::Constants::HalfPi);
  429. for (auto& vertex : planeXY.m_vertices)
  430. {
  431. vertex.Set(
  432. rotation90Y.TransformPoint(vertex.GetAsVector3()),
  433. vertex.GetW()
  434. );
  435. }
  436. AZStd::vector<AZ::Vector3> normals;
  437. AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateNormals(
  438. planeXY.m_vertices, planeXY.m_indices, normals);
  439. AZStd::vector<AZ::Vector3> tangents;
  440. AZStd::vector<AZ::Vector3> bitangents;
  441. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentsAndBitagents(
  442. planeXY.m_vertices, planeXY.m_indices, planeXY.m_uvs, normals,
  443. tangents, bitangents);
  444. EXPECT_TRUE(tangentsCalculated);
  445. EXPECT_EQ(tangents.size(), numVertices);
  446. EXPECT_EQ(bitangents.size(), numVertices);
  447. EXPECT_THAT(tangents, ::testing::Each(IsCloseTolerance(-AZ::Vector3::CreateAxisZ(), Tolerance)));
  448. EXPECT_THAT(bitangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisY(), Tolerance)));
  449. }
  450. TEST(NvClothSystem, TangentSpaceHelper_CalculateTangentSpacePlaneXYRot90Y_ReturnsCorrectTangentSpace)
  451. {
  452. const float width = 1.0f;
  453. const float height = 1.0f;
  454. const AZ::u32 segmentsX = 5;
  455. const AZ::u32 segmentsY = 5;
  456. TriangleInput planeXY = CreatePlane(width, height, segmentsX, segmentsY);
  457. const size_t numVertices = planeXY.m_vertices.size();
  458. const AZ::Transform rotation90Y = AZ::Transform::CreateRotationY(AZ::Constants::HalfPi);
  459. for (auto& vertex : planeXY.m_vertices)
  460. {
  461. vertex.Set(
  462. rotation90Y.TransformPoint(vertex.GetAsVector3()),
  463. vertex.GetW()
  464. );
  465. }
  466. AZStd::vector<AZ::Vector3> tangents;
  467. AZStd::vector<AZ::Vector3> bitangents;
  468. AZStd::vector<AZ::Vector3> normals;
  469. bool tangentsCalculated = AZ::Interface<NvCloth::ITangentSpaceHelper>::Get()->CalculateTangentSpace(
  470. planeXY.m_vertices, planeXY.m_indices, planeXY.m_uvs,
  471. tangents, bitangents, normals);
  472. EXPECT_TRUE(tangentsCalculated);
  473. EXPECT_EQ(tangents.size(), numVertices);
  474. EXPECT_EQ(bitangents.size(), numVertices);
  475. EXPECT_EQ(normals.size(), numVertices);
  476. EXPECT_THAT(tangents, ::testing::Each(IsCloseTolerance(-AZ::Vector3::CreateAxisZ(), Tolerance)));
  477. EXPECT_THAT(bitangents, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisY(), Tolerance)));
  478. EXPECT_THAT(normals, ::testing::Each(IsCloseTolerance(AZ::Vector3::CreateAxisX(), Tolerance)));
  479. }
  480. } // namespace UnitTest