MatrixUtilsTests.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 <AzCore/Math/MatrixUtils.h>
  9. #include <AzCore/UnitTest/TestTypes.h>
  10. namespace UnitTest
  11. {
  12. using namespace AZ;
  13. class MatrixUtilsTests : public LeakDetectionFixture
  14. {
  15. protected:
  16. const float floatEpsilon = 0.001f;
  17. };
  18. TEST_F(MatrixUtilsTests, PerspectiveMatrixFovRH)
  19. {
  20. Matrix4x4 matrix;
  21. constexpr float near_value = 10.0f;
  22. constexpr float far_value = 1000.0f;
  23. float fovY = Constants::HalfPi;
  24. float aspectRatio = 1.0f;
  25. auto matPtr = MakePerspectiveFovMatrixRH(matrix, fovY, aspectRatio, near_value, far_value);
  26. EXPECT_NE(matPtr, nullptr);
  27. EXPECT_EQ(matPtr, &matrix);
  28. // transform some positions and valid the output
  29. // point on near plane
  30. Vector3 nearPos(0.0f, 0.0f, -near_value);
  31. Vector3 result = MatrixTransformPosition(matrix, nearPos);
  32. EXPECT_NEAR(result.GetZ(), 0.0f, floatEpsilon);
  33. // point on far plane
  34. Vector3 farPos(0.0f, 0.0f, -far_value);
  35. result = MatrixTransformPosition(matrix, farPos);
  36. EXPECT_NEAR(result.GetZ(), 1.0f, floatEpsilon);
  37. // point further than far plane
  38. Vector3 furtherFarPos(0.0f, 0.0f, -far_value - 1000.0f);
  39. result = MatrixTransformPosition(matrix, furtherFarPos);
  40. EXPECT_GT(result.GetZ(), 1.0f);
  41. // point closer then near plane
  42. Vector3 closerNearPos(0.0f, 0.0f, -near_value + 5.0f);
  43. result = MatrixTransformPosition(matrix, closerNearPos);
  44. EXPECT_LT(result.GetZ(), 0.0f);
  45. // point between near and far
  46. Vector3 betweenPos(0.0f, 0.0f, -(far_value + near_value) / 2.0f);
  47. result = MatrixTransformPosition(matrix, betweenPos);
  48. EXPECT_GT(result.GetZ(), 0.0f);
  49. EXPECT_LT(result.GetZ(), 1.0f);
  50. // x and y value
  51. Vector3 insideLeftTopPos(-900.0f, 900.0f, -far_value);
  52. Vector3 insideRightBottomPos(900.0f, -900.0f, -far_value);
  53. Vector3 outsideLeftTopPos(-1100.0f, 1100.0f, -far_value);
  54. Vector3 outsideRightBottomPos(1100.0f, -1100.0f, -far_value);
  55. result = MatrixTransformPosition(matrix, insideLeftTopPos);
  56. EXPECT_LT(result.GetX(), 0.0f);
  57. EXPECT_GT(result.GetX(), -1.0f);
  58. EXPECT_GT(result.GetY(), 0.0f);
  59. EXPECT_LT(result.GetY(), 1.0f);
  60. result = MatrixTransformPosition(matrix, insideRightBottomPos);
  61. EXPECT_GT(result.GetX(), 0.0f);
  62. EXPECT_LT(result.GetX(), 1.0f);
  63. EXPECT_LT(result.GetY(), 0.0f);
  64. EXPECT_GT(result.GetY(), -1.0f);
  65. result = MatrixTransformPosition(matrix, outsideLeftTopPos);
  66. EXPECT_LT(result.GetX(), -1.0f);
  67. EXPECT_GT(result.GetY(), 1.0f);
  68. result = MatrixTransformPosition(matrix, outsideRightBottomPos);
  69. EXPECT_GT(result.GetX(), 1.0f);
  70. EXPECT_LT(result.GetY(), -1.0f);
  71. // create a reverse depth perspective projection matrix
  72. MakePerspectiveFovMatrixRH(matrix, fovY, aspectRatio, near_value, far_value, true);
  73. result = MatrixTransformPosition(matrix, nearPos);
  74. EXPECT_NEAR(result.GetZ(), 1.0f, floatEpsilon);
  75. result = MatrixTransformPosition(matrix, farPos);
  76. EXPECT_NEAR(result.GetZ(), 0.0f, floatEpsilon);
  77. result = MatrixTransformPosition(matrix, furtherFarPos);
  78. EXPECT_LT(result.GetZ(), 0.0f);
  79. result = MatrixTransformPosition(matrix, closerNearPos);
  80. EXPECT_GT(result.GetZ(), 1.0f);
  81. result = MatrixTransformPosition(matrix, betweenPos);
  82. EXPECT_GT(result.GetZ(), 0.0f);
  83. EXPECT_LT(result.GetZ(), 1.0f);
  84. result = MatrixTransformPosition(matrix, insideLeftTopPos);
  85. EXPECT_LT(result.GetX(), 0.0f);
  86. EXPECT_GT(result.GetX(), -1.0f);
  87. EXPECT_GT(result.GetY(), 0.0f);
  88. EXPECT_LT(result.GetY(), 1.0f);
  89. result = MatrixTransformPosition(matrix, insideRightBottomPos);
  90. EXPECT_GT(result.GetX(), 0.0f);
  91. EXPECT_LT(result.GetX(), 1.0f);
  92. EXPECT_LT(result.GetY(), 0.0f);
  93. EXPECT_GT(result.GetY(), -1.0f);
  94. result = MatrixTransformPosition(matrix, outsideLeftTopPos);
  95. EXPECT_LT(result.GetX(), -1.0f);
  96. EXPECT_GT(result.GetY(), 1.0f);
  97. result = MatrixTransformPosition(matrix, outsideRightBottomPos);
  98. EXPECT_GT(result.GetX(), 1.0f);
  99. EXPECT_LT(result.GetY(), -1.0f);
  100. // bad input
  101. UnitTest::TestRunner::Instance().StartAssertTests();
  102. EXPECT_FALSE(MakePerspectiveFovMatrixRH(matrix, fovY, -1.0f, near_value, far_value));
  103. EXPECT_EQ(1, UnitTest::TestRunner::Instance().m_numAssertsFailed);
  104. EXPECT_FALSE(MakePerspectiveFovMatrixRH(matrix, 0.0f, aspectRatio, near_value, far_value));
  105. EXPECT_EQ(2, UnitTest::TestRunner::Instance().m_numAssertsFailed);
  106. EXPECT_FALSE(MakePerspectiveFovMatrixRH(matrix, fovY, aspectRatio, -near_value, far_value));
  107. EXPECT_EQ(3, UnitTest::TestRunner::Instance().m_numAssertsFailed);
  108. EXPECT_FALSE(MakePerspectiveFovMatrixRH(matrix, fovY, aspectRatio, near_value, -far_value));
  109. EXPECT_EQ(4, UnitTest::TestRunner::Instance().m_numAssertsFailed);
  110. EXPECT_FALSE(MakePerspectiveFovMatrixRH(matrix, fovY, aspectRatio, 0.0f, far_value));
  111. EXPECT_EQ(5, UnitTest::TestRunner::Instance().m_numAssertsFailed);
  112. UnitTest::TestRunner::Instance().StopAssertTests();
  113. }
  114. TEST_F(MatrixUtilsTests, OrthographicMatrixRH)
  115. {
  116. Matrix4x4 matrix;
  117. auto ptr = MakeOrthographicMatrixRH(matrix, -100.0f, 0.0f, 100.0f, 200.0f, 0.0f, 1000.0f);
  118. EXPECT_NE(ptr, nullptr);
  119. EXPECT_EQ(ptr, &matrix);
  120. Vector3 result;
  121. // center position
  122. result = MatrixTransformPosition(matrix, Vector3(-50.0f, 150.0f, -500.0f));
  123. EXPECT_NEAR(result.GetX(), 0.0f, floatEpsilon);
  124. EXPECT_NEAR(result.GetY(), 0.0f, floatEpsilon);
  125. EXPECT_NEAR(result.GetZ(), 0.5f, floatEpsilon);
  126. // left top and far
  127. result = MatrixTransformPosition(matrix, Vector3(-100.0f, 200.0f, -1000.0f));
  128. EXPECT_NEAR(result.GetX(), -1.0f, floatEpsilon);
  129. EXPECT_NEAR(result.GetY(), 1.0f, floatEpsilon);
  130. EXPECT_NEAR(result.GetZ(), 1.0f, floatEpsilon);
  131. // right bottom and near
  132. result = MatrixTransformPosition(matrix, Vector3(0.0f, 100.0f, 0.0f));
  133. EXPECT_NEAR(result.GetX(), 1.0f, floatEpsilon);
  134. EXPECT_NEAR(result.GetY(), -1.0f, floatEpsilon);
  135. EXPECT_NEAR(result.GetZ(), 0.0f, floatEpsilon);
  136. // further than far
  137. result = MatrixTransformPosition(matrix, Vector3(-50.0f, 150.0f, -2000.0f));
  138. EXPECT_GT(result.GetZ(), 1.0f);
  139. // closer than near
  140. result = MatrixTransformPosition(matrix, Vector3(-50.0f, 150.0f, 200.0f));
  141. EXPECT_LT(result.GetZ(), 0.0f);
  142. }
  143. TEST_F(MatrixUtilsTests, FrustumMatrixRH)
  144. {
  145. Matrix4x4 matrix;
  146. auto ptr = MakeFrustumMatrixRH(matrix, -100.0f, 0.0f, 100.0f, 200.0f, 1.0f, 1000.0f);
  147. EXPECT_NE(ptr, nullptr);
  148. EXPECT_EQ(ptr, &matrix);
  149. Vector3 result;
  150. // left top and near
  151. Vector3 leftTopNear(-100.0f, 200.0f, -1.0f);
  152. result = MatrixTransformPosition(matrix, leftTopNear);
  153. EXPECT_NEAR(result.GetX(), -1.0f, floatEpsilon);
  154. EXPECT_NEAR(result.GetY(), 1.0f, floatEpsilon);
  155. EXPECT_NEAR(result.GetZ(), 0.0f, floatEpsilon);
  156. // right bottom and near
  157. Vector3 rightBottomNear(0.0f, 100.0f, -1.0f);
  158. result = MatrixTransformPosition(matrix, rightBottomNear);
  159. EXPECT_NEAR(result.GetX(), 1.0f, floatEpsilon);
  160. EXPECT_NEAR(result.GetY(), -1.0f, floatEpsilon);
  161. EXPECT_NEAR(result.GetZ(), 0.0f, floatEpsilon);
  162. // further than far
  163. Vector3 far_value(-50.0f, 150.0f, -1000.0f);
  164. result = MatrixTransformPosition(matrix, far_value);
  165. EXPECT_NEAR(result.GetZ(), 1.0f, floatEpsilon);
  166. Vector3 furtherFar(-50.0f, 150.0f, -2000.0f);
  167. result = MatrixTransformPosition(matrix, furtherFar);
  168. EXPECT_GT(result.GetZ(), 1.0f);
  169. // closer than near
  170. Vector3 closerNear(-50.0f, 150.0f, -0.5f);
  171. result = MatrixTransformPosition(matrix, closerNear);
  172. EXPECT_LT(result.GetZ(), 0.0f);
  173. // reverse depth
  174. MakeFrustumMatrixRH(matrix, -100.0f, 0.0f, 100.0f, 200.0f, 1.0f, 1000.0f, true);
  175. result = MatrixTransformPosition(matrix, leftTopNear);
  176. EXPECT_NEAR(result.GetX(), -1.0f, floatEpsilon);
  177. EXPECT_NEAR(result.GetY(), 1.0f, floatEpsilon);
  178. result = MatrixTransformPosition(matrix, rightBottomNear);
  179. EXPECT_NEAR(result.GetX(), 1.0f, floatEpsilon);
  180. EXPECT_NEAR(result.GetY(), -1.0f, floatEpsilon);
  181. EXPECT_NEAR(result.GetZ(), 1.0f, floatEpsilon);
  182. result = MatrixTransformPosition(matrix, far_value);
  183. EXPECT_NEAR(result.GetZ(), 0.0f, floatEpsilon);
  184. // bad input
  185. UnitTest::TestRunner::Instance().StartAssertTests();
  186. // near = 0
  187. EXPECT_FALSE(MakeFrustumMatrixRH(matrix, -100.0f, 0.0f, 100.0f, 200.0f, 0.0f, 1000.0f));
  188. EXPECT_EQ(1, UnitTest::TestRunner::Instance().m_numAssertsFailed);
  189. UnitTest::TestRunner::Instance().StopAssertTests();
  190. }
  191. }