EditorAreaLightComponentTests.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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 <Atom/Feature/CoreLights/CapsuleLightFeatureProcessorInterface.h>
  9. #include <Atom/RPI.Public/Base.h>
  10. #include <Atom/RPI.Public/FeatureProcessorFactory.h>
  11. #include <Atom/RPI.Public/RPISystem.h>
  12. #include <Atom/RPI.Public/Scene.h>
  13. #include <Atom/RPI.Reflect/System/SceneDescriptor.h>
  14. #include <AzFramework/Visibility/BoundsBus.h>
  15. #include <AzTest/AzTest.h>
  16. #include <AZTestShared/Utils/Utils.h>
  17. #include <AzToolsFramework/ToolsComponents/TransformComponent.h>
  18. #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
  19. #include <CoreLights/EditorAreaLightComponent.h>
  20. #include <LmbrCentral/Shape/CapsuleShapeComponentBus.h>
  21. #include <LmbrCentral/Shape/DiskShapeComponentBus.h>
  22. #include <LmbrCentral/Shape/PolygonPrismShapeComponentBus.h>
  23. #include <LmbrCentral/Shape/QuadShapeComponentBus.h>
  24. #include <LmbrCentral/Shape/SphereShapeComponentBus.h>
  25. namespace UnitTest
  26. {
  27. using EditorAreaLightComponentFixture = ::testing::Test;
  28. AZ::Render::AreaLightComponentConfig CreateAreaLightComponentConfig(
  29. const AZ::Render::AreaLightComponentConfig::LightType lightType,
  30. const float attenuationRadius,
  31. const bool enableShutters = false,
  32. const float innerShutterAngleDegrees = 0.0f,
  33. const float outerShutterAngleDegrees = 0.0f)
  34. {
  35. AZ::Render::AreaLightComponentConfig areaLightComponentConfig;
  36. areaLightComponentConfig.m_lightType = lightType;
  37. areaLightComponentConfig.m_attenuationRadiusMode = AZ::Render::LightAttenuationRadiusMode::Explicit;
  38. areaLightComponentConfig.m_attenuationRadius = attenuationRadius;
  39. areaLightComponentConfig.m_enableShutters = enableShutters;
  40. areaLightComponentConfig.m_innerShutterAngleDegrees = innerShutterAngleDegrees;
  41. areaLightComponentConfig.m_outerShutterAngleDegrees = outerShutterAngleDegrees;
  42. return areaLightComponentConfig;
  43. }
  44. static AZStd::unique_ptr<AZ::Entity> CreateEditorAreaLightEntity(
  45. const AZ::Render::AreaLightComponentConfig& areaLightComponentConfig,
  46. const AZStd::optional<AZ::TypeId>& shapeTypeId = AZStd::nullopt,
  47. const AZ::Vector3& shapeOffset = AZ::Vector3::CreateZero())
  48. {
  49. auto entity = AZStd::make_unique<AZ::Entity>();
  50. entity->Init();
  51. entity->CreateComponent<AzToolsFramework::Components::TransformComponent>();
  52. if (shapeTypeId.has_value())
  53. {
  54. entity->CreateComponent(shapeTypeId.value());
  55. }
  56. entity->AddComponent(aznew AZ::Render::EditorAreaLightComponent(areaLightComponentConfig));
  57. entity->Activate();
  58. LmbrCentral::ShapeComponentRequestsBus::Event(
  59. entity->GetId(), &LmbrCentral::ShapeComponentRequests::SetTranslationOffset, shapeOffset);
  60. return entity;
  61. }
  62. static void SetCapsuleShapeHeightAndRadius(const AZ::EntityId entityId, const float height, const float radius)
  63. {
  64. LmbrCentral::CapsuleShapeComponentRequestsBus::Event(
  65. entityId, &LmbrCentral::CapsuleShapeComponentRequestsBus::Events::SetHeight, height);
  66. LmbrCentral::CapsuleShapeComponentRequestsBus::Event(
  67. entityId, &LmbrCentral::CapsuleShapeComponentRequestsBus::Events::SetRadius, radius);
  68. }
  69. static void SetDiskShapeRadius(const AZ::EntityId entityId, const float radius)
  70. {
  71. LmbrCentral::DiskShapeComponentRequestBus::Event(entityId, &LmbrCentral::DiskShapeComponentRequestBus::Events::SetRadius, radius);
  72. }
  73. static void SetQuadShapeWidthAndHeight(const AZ::EntityId entityId, const float width, const float height)
  74. {
  75. LmbrCentral::QuadShapeComponentRequestBus::Event(entityId, &LmbrCentral::QuadShapeComponentRequestBus::Events::SetQuadWidth, width);
  76. LmbrCentral::QuadShapeComponentRequestBus::Event(
  77. entityId, &LmbrCentral::QuadShapeComponentRequestBus::Events::SetQuadHeight, height);
  78. }
  79. static void SetPolygonShapeVertices(const AZ::EntityId entityId, const AZStd::vector<AZ::Vector2>& vertices)
  80. {
  81. LmbrCentral::PolygonPrismShapeComponentRequestBus::Event(
  82. entityId, &LmbrCentral::PolygonPrismShapeComponentRequestBus::Events::SetVertices, vertices);
  83. }
  84. static void SetSphereShapeRadius(const AZ::EntityId entityId, const float radius)
  85. {
  86. LmbrCentral::SphereShapeComponentRequestsBus::Event(
  87. entityId, &LmbrCentral::SphereShapeComponentRequestsBus::Events::SetRadius, radius);
  88. }
  89. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaCapsuleLightBounds)
  90. {
  91. // suppress warning when feature process is not created in test environment
  92. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::CapsuleLightFeatureProcessorInterface on the scene.");
  93. // capsule shape contained within attenuation radius (effectively a sphere)
  94. {
  95. auto entity = CreateEditorAreaLightEntity(
  96. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 10.0f),
  97. LmbrCentral::EditorCapsuleShapeComponentTypeId);
  98. SetCapsuleShapeHeightAndRadius(entity->GetId(), 10.0f, 2.0f);
  99. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  100. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-10.0f), AZ::Vector3(10.0f))));
  101. }
  102. // capsule shape contained within attenuation radius with capsule height contributing to overall height
  103. {
  104. auto entity = CreateEditorAreaLightEntity(
  105. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 10.0f),
  106. LmbrCentral::EditorCapsuleShapeComponentTypeId);
  107. SetCapsuleShapeHeightAndRadius(entity->GetId(), 40.0f, 2.0f);
  108. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  109. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-10.0f, -10.0f, -20.0f), AZ::Vector3(10.0f, 10.0f, 20.0f))));
  110. }
  111. // attenuation radius contained within capsule shape
  112. {
  113. auto entity = CreateEditorAreaLightEntity(
  114. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 10.0f),
  115. LmbrCentral::EditorCapsuleShapeComponentTypeId);
  116. SetCapsuleShapeHeightAndRadius(entity->GetId(), 40.0f, 15.0f);
  117. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  118. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-15.0f, -15.0f, -20.0f), AZ::Vector3(15.0f, 15.0f, 20.0f))));
  119. }
  120. // attenuation radius contained within capsule shape (now effectively a sphere)
  121. {
  122. auto entity = CreateEditorAreaLightEntity(
  123. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 10.0f),
  124. LmbrCentral::EditorCapsuleShapeComponentTypeId);
  125. SetCapsuleShapeHeightAndRadius(entity->GetId(), 50.0f, 25.0f);
  126. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  127. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-25.0f), AZ::Vector3(25.0f))));
  128. }
  129. }
  130. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaCapsuleLightWithShapeTranslationOffsetBounds)
  131. {
  132. // suppress warning when feature process is not created in test environment
  133. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::CapsuleLightFeatureProcessorInterface on the scene.");
  134. // capsule shape contained within attenuation radius (effectively a sphere)
  135. {
  136. const AZ::Vector3 shapeTranslationOffset(4.0f, 7.0f, 2.0f);
  137. auto entity = CreateEditorAreaLightEntity(
  138. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 15.0f),
  139. LmbrCentral::EditorCapsuleShapeComponentTypeId, shapeTranslationOffset);
  140. SetCapsuleShapeHeightAndRadius(entity->GetId(), 12.0f, 1.0f);
  141. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  142. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-11.0f, -8.0f, -13.0f), AZ::Vector3(19.0f, 22.0f, 17.0f))));
  143. }
  144. // capsule shape contained within attenuation radius with capsule height contributing to overall height
  145. {
  146. const AZ::Vector3 shapeTranslationOffset(6.0f, -11.0f, 13.0f);
  147. auto entity = CreateEditorAreaLightEntity(
  148. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 5.0f),
  149. LmbrCentral::EditorCapsuleShapeComponentTypeId, shapeTranslationOffset);
  150. SetCapsuleShapeHeightAndRadius(entity->GetId(), 30.0f, 4.0f);
  151. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  152. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(1.0f, -16.0f, -2.0f), AZ::Vector3(11.0f, -6.0f, 28.0f))));
  153. }
  154. // attenuation radius contained within capsule shape
  155. {
  156. const AZ::Vector3 shapeTranslationOffset(-7.0f, -7.0f, 4.0f);
  157. auto entity = CreateEditorAreaLightEntity(
  158. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 5.0f),
  159. LmbrCentral::EditorCapsuleShapeComponentTypeId, shapeTranslationOffset);
  160. SetCapsuleShapeHeightAndRadius(entity->GetId(), 50.0f, 12.0f);
  161. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  162. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-19.0f, -19.0f, -21.0f), AZ::Vector3(5.0f, 5.0f, 29.0f))));
  163. }
  164. // attenuation radius contained within capsule shape (now effectively a sphere)
  165. {
  166. const AZ::Vector3 shapeTranslationOffset(8.0f, -13.0f, 9.0f);
  167. auto entity = CreateEditorAreaLightEntity(
  168. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 8.0f),
  169. LmbrCentral::EditorCapsuleShapeComponentTypeId, shapeTranslationOffset);
  170. SetCapsuleShapeHeightAndRadius(entity->GetId(), 30.0f, 20.0f);
  171. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  172. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-12.0f, -33.0f, -11.0f), AZ::Vector3(28.0f, 7.0f, 29.0f))));
  173. }
  174. }
  175. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaCapsuleLightSurfaceArea)
  176. {
  177. // suppress warning when feature process is not created in test environment
  178. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::CapsuleLightFeatureProcessorInterface on the scene.");
  179. auto entity = CreateEditorAreaLightEntity(
  180. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Capsule, 10.0f),
  181. LmbrCentral::EditorCapsuleShapeComponentTypeId);
  182. // note: radius will be 10.0 after scale is applied
  183. SetCapsuleShapeHeightAndRadius(entity->GetId(), 20.0f, 5.0f);
  184. AZ::TransformBus::Event(entity->GetId(), &AZ::TransformBus::Events::SetLocalUniformScale, 2.0f);
  185. // 4.0f * Pi * radius * radius - both caps make a sphere
  186. // 2.0f * Pi * radius * innerHeight - cylindrical area of capsule
  187. float lightDelegateSurfaceArea = 0.0f;
  188. AZ::Render::AreaLightRequestBus::EventResult(
  189. lightDelegateSurfaceArea, entity->GetId(), &AZ::Render::AreaLightRequestBus::Events::GetSurfaceArea);
  190. using ::testing::FloatNear;
  191. EXPECT_THAT(lightDelegateSurfaceArea, FloatNear(2513.27412287f, AZ::Constants::FloatEpsilon));
  192. }
  193. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaSpotDiskLightBounds)
  194. {
  195. // suppress warning when feature process is not created in test environment
  196. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::DiskLightFeatureProcessorInterface on the scene.");
  197. // inner angle smaller and taller
  198. {
  199. auto entity = CreateEditorAreaLightEntity(
  200. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SpotDisk, 10.0f, true, 15.0f, 30.0f),
  201. LmbrCentral::EditorDiskShapeComponentTypeId);
  202. SetDiskShapeRadius(entity->GetId(), 1.0f);
  203. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  204. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-6.0f, -6.0f, 0.0f), AZ::Vector3(6.0f, 6.0f, 9.65926f))));
  205. }
  206. // inner angle smaller and taller with larger base radius
  207. {
  208. auto entity = CreateEditorAreaLightEntity(
  209. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SpotDisk, 10.0f, true, 15.0f, 30.0f),
  210. LmbrCentral::EditorDiskShapeComponentTypeId);
  211. SetDiskShapeRadius(entity->GetId(), 2.0f);
  212. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  213. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-7.0f, -7.0f, 0.0f), AZ::Vector3(7.0f, 7.0f, 9.65926f))));
  214. }
  215. // inner angle larger and clamped to outer angle
  216. {
  217. auto entity = CreateEditorAreaLightEntity(
  218. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SpotDisk, 10.0f, true, 40.0f, 30.0f),
  219. LmbrCentral::EditorDiskShapeComponentTypeId);
  220. SetDiskShapeRadius(entity->GetId(), 1.0f);
  221. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  222. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-6.0f, -6.0f, 0.0f), AZ::Vector3(6.0f, 6.0f, 8.66025f))));
  223. }
  224. // inner and outer angle the same, wide angle
  225. {
  226. auto entity = CreateEditorAreaLightEntity(
  227. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SpotDisk, 5.0f, true, 60.0f, 60.0f),
  228. LmbrCentral::EditorDiskShapeComponentTypeId);
  229. SetDiskShapeRadius(entity->GetId(), 2.0f);
  230. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  231. EXPECT_THAT(
  232. aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-6.33013f, -6.33013f, 0.0f), AZ::Vector3(6.33013f, 6.33013f, 2.5f))));
  233. }
  234. // inner and outer angles disabled
  235. {
  236. auto entity = CreateEditorAreaLightEntity(
  237. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SpotDisk, 8.0f),
  238. LmbrCentral::EditorDiskShapeComponentTypeId);
  239. SetDiskShapeRadius(entity->GetId(), 5.0f);
  240. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  241. EXPECT_THAT(
  242. aabb,
  243. IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-8.38095f, -8.38095f, 0.0f), AZ::Vector3(8.38095f, 8.38095f, 7.25046f))));
  244. }
  245. }
  246. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaSimpleSpotLightBounds)
  247. {
  248. // suppress warning when feature process is not created in test environment
  249. UnitTest::ErrorHandler featureProcessorNotFound(
  250. "Unable to find a AZ::Render::SimpleSpotLightFeatureProcessorInterface on the scene.");
  251. // inner angle smaller and taller
  252. {
  253. auto entity = CreateEditorAreaLightEntity(
  254. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SimpleSpot, 10.0f, true, 15.0f, 30.0f));
  255. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  256. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-5.0f, -5.0f, 0.0f), AZ::Vector3(5.0f, 5.0f, 9.65926f))));
  257. }
  258. // inner angle larger and clamped to outer angle
  259. {
  260. auto entity = CreateEditorAreaLightEntity(
  261. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SimpleSpot, 10.0f, true, 40.0f, 30.0f));
  262. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  263. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-5.0f, -5.0f, 0.0f), AZ::Vector3(5.0f, 5.0f, 8.66025f))));
  264. }
  265. }
  266. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaQuadLightBounds)
  267. {
  268. // suppress warning when feature process is not created in test environment
  269. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::QuadLightFeatureProcessorInterface on the scene.");
  270. // quad contained within attenuation sphere
  271. {
  272. auto entity = CreateEditorAreaLightEntity(
  273. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Quad, 15.0f),
  274. LmbrCentral::EditorQuadShapeComponentTypeId);
  275. SetQuadShapeWidthAndHeight(entity->GetId(), 5.0f, 5.0f);
  276. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  277. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-15.0f), AZ::Vector3(15.0f))));
  278. }
  279. // quad larger than attenuation sphere
  280. {
  281. auto entity = CreateEditorAreaLightEntity(
  282. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Quad, 15.0f),
  283. LmbrCentral::EditorQuadShapeComponentTypeId);
  284. SetQuadShapeWidthAndHeight(entity->GetId(), 50.0f, 50.0f);
  285. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  286. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-25.0f, -25.0f, -15.0f), AZ::Vector3(25.0f, 25.0f, 15.0f))));
  287. }
  288. }
  289. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaPolygonLightBounds)
  290. {
  291. // suppress warning when feature process is not created in test environment
  292. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::PolygonLightFeatureProcessorInterface on the scene.");
  293. // polygon contained within attenuation sphere
  294. {
  295. auto entity = CreateEditorAreaLightEntity(
  296. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Polygon, 15.0f),
  297. LmbrCentral::EditorPolygonPrismShapeComponentTypeId);
  298. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  299. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-15.0f), AZ::Vector3(15.0f))));
  300. }
  301. // polygon outside attenuation sphere
  302. {
  303. auto entity = CreateEditorAreaLightEntity(
  304. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Polygon, 15.0f),
  305. LmbrCentral::EditorPolygonPrismShapeComponentTypeId);
  306. SetPolygonShapeVertices(
  307. entity->GetId(),
  308. AZStd::vector<AZ::Vector2>{
  309. AZ::Vector2(-50.0f, -50.0f), AZ::Vector2(50.0f, -50.0f), AZ::Vector2(50.0f, 50.0f), AZ::Vector2(-50.0f, 50.0f) });
  310. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  311. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-50.0f, -50.0f, -15.0f), AZ::Vector3(50.0f, 50.0f, 15.0f))));
  312. }
  313. }
  314. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaPointSphereLightBounds)
  315. {
  316. // suppress warning when feature process is not created in test environment
  317. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::PointLightFeatureProcessorInterface on the scene.");
  318. // sphere shape contained within attenuation sphere
  319. {
  320. auto entity = CreateEditorAreaLightEntity(
  321. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Sphere, 15.0f),
  322. LmbrCentral::EditorSphereShapeComponentTypeId);
  323. SetSphereShapeRadius(entity->GetId(), 5.0f);
  324. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  325. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-15.0f), AZ::Vector3(15.0f))));
  326. }
  327. // sphere shape contained within attenuation sphere
  328. {
  329. auto entity = CreateEditorAreaLightEntity(
  330. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Sphere, 15.0f),
  331. LmbrCentral::EditorSphereShapeComponentTypeId);
  332. SetSphereShapeRadius(entity->GetId(), 30.0f);
  333. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  334. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-30.0f), AZ::Vector3(30.0f))));
  335. }
  336. }
  337. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaPointSphereLightWithShapeTranslationOffsetBounds)
  338. {
  339. // suppress warning when feature process is not created in test environment
  340. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::PointLightFeatureProcessorInterface on the scene.");
  341. // sphere shape contained within attenuation sphere
  342. {
  343. const AZ::Vector3 shapeTranslationOffset(5.0f, 8.0f, -7.0f);
  344. auto entity = CreateEditorAreaLightEntity(
  345. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Sphere, 20.0f),
  346. LmbrCentral::EditorSphereShapeComponentTypeId, shapeTranslationOffset);
  347. SetSphereShapeRadius(entity->GetId(), 8.0f);
  348. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  349. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-15.0f, -12.0f, -27.0f), AZ::Vector3(25.0f, 28.0f, 13.0f))));
  350. }
  351. // sphere shape contained within attenuation sphere
  352. {
  353. const AZ::Vector3 shapeTranslationOffset(-7.0f, -2.0f, 6.0f);
  354. auto entity = CreateEditorAreaLightEntity(
  355. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Sphere, 12.0f),
  356. LmbrCentral::EditorSphereShapeComponentTypeId, shapeTranslationOffset);
  357. SetSphereShapeRadius(entity->GetId(), 25.0f);
  358. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  359. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-32.0f, -27.0f, -19.0f), AZ::Vector3(18.0f, 23.0f, 31.0f))));
  360. }
  361. }
  362. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaPointSphereLightSurfaceArea)
  363. {
  364. // suppress warning when feature process is not created in test environment
  365. UnitTest::ErrorHandler featureProcessorNotFound("Unable to find a AZ::Render::PointLightFeatureProcessorInterface on the scene.");
  366. auto entity = CreateEditorAreaLightEntity(
  367. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::Sphere, 10.0f),
  368. LmbrCentral::EditorSphereShapeComponentTypeId);
  369. // note: radius will be 10.0 after scale is applied
  370. SetSphereShapeRadius(entity->GetId(), 5.0f);
  371. AZ::TransformBus::Event(entity->GetId(), &AZ::TransformBus::Events::SetLocalUniformScale, 2.0f);
  372. // 4.0f * Pi * radius * radius
  373. float lightDelegateSurfaceArea = 0.0f;
  374. AZ::Render::AreaLightRequestBus::EventResult(
  375. lightDelegateSurfaceArea, entity->GetId(), &AZ::Render::AreaLightRequestBus::Events::GetSurfaceArea);
  376. using ::testing::FloatNear;
  377. EXPECT_THAT(lightDelegateSurfaceArea, FloatNear(1256.6370614f, AZ::Constants::FloatEpsilon));
  378. }
  379. TEST_F(EditorAreaLightComponentFixture, CheckEditorAreaSimplePointLightBounds)
  380. {
  381. // suppress warning when feature process is not created in test environment
  382. UnitTest::ErrorHandler featureProcessorNotFound(
  383. "Unable to find a AZ::Render::SimplePointLightFeatureProcessorInterface on the scene.");
  384. {
  385. auto entity = CreateEditorAreaLightEntity(
  386. CreateAreaLightComponentConfig(AZ::Render::AreaLightComponentConfig::LightType::SimplePoint, 15.0f),
  387. LmbrCentral::EditorSphereShapeComponentTypeId);
  388. const AZ::Aabb aabb = AzFramework::CalculateEntityLocalBoundsUnion(entity.get());
  389. EXPECT_THAT(aabb, IsClose(AZ::Aabb::CreateFromMinMax(AZ::Vector3(-15.0f), AZ::Vector3(15.0f))));
  390. }
  391. }
  392. } // namespace UnitTest