helmet_renderers_test.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. #include "render/equipment/equipment_registry.h"
  2. #include "render/equipment/helmets/headwrap.h"
  3. #include "render/equipment/helmets/montefortino_helmet.h"
  4. #include "render/humanoid/rig.h"
  5. #include "render/palette.h"
  6. #include <gtest/gtest.h>
  7. #include <memory>
  8. using namespace Render::GL;
  9. namespace {
  10. // Mock submitter for testing
  11. class MockSubmitter : public ISubmitter {
  12. public:
  13. void mesh(Mesh * /*mesh*/, const QMatrix4x4 & /*transform*/,
  14. const QVector3D & /*color*/, Texture * /*texture*/,
  15. float /*alpha*/) override {
  16. mesh_count++;
  17. }
  18. void cylinder(const QVector3D & /*start*/, const QVector3D & /*end*/,
  19. float /*radius*/, const QVector3D & /*color*/,
  20. float /*alpha*/) override {
  21. cylinder_count++;
  22. }
  23. void selectionRing(const QMatrix4x4 & /*model*/, float /*alphaInner*/,
  24. float /*alphaOuter*/,
  25. const QVector3D & /*color*/) override {
  26. // Not used in helmet rendering
  27. }
  28. void grid(const QMatrix4x4 & /*model*/, const QVector3D & /*color*/,
  29. float /*cellSize*/, float /*thickness*/,
  30. float /*extent*/) override {
  31. // Not used in helmet rendering
  32. }
  33. void selectionSmoke(const QMatrix4x4 & /*model*/, const QVector3D & /*color*/,
  34. float /*baseAlpha*/) override {
  35. // Not used in helmet rendering
  36. }
  37. int mesh_count = 0;
  38. int cylinder_count = 0;
  39. };
  40. // Helper to create a basic DrawContext
  41. DrawContext createTestContext() {
  42. DrawContext ctx;
  43. ctx.model.setToIdentity();
  44. ctx.backend = nullptr;
  45. ctx.entity = nullptr;
  46. return ctx;
  47. }
  48. // Helper to create basic body frames
  49. BodyFrames createTestFrames() {
  50. BodyFrames frames;
  51. frames.head.origin = QVector3D(0.0F, 1.7F, 0.0F);
  52. frames.head.right = QVector3D(1.0F, 0.0F, 0.0F);
  53. frames.head.up = QVector3D(0.0F, 1.0F, 0.0F);
  54. frames.head.forward = QVector3D(0.0F, 0.0F, 1.0F);
  55. frames.head.radius = 0.12F;
  56. return frames;
  57. }
  58. // Helper to create basic palette
  59. HumanoidPalette createTestPalette() {
  60. HumanoidPalette palette;
  61. palette.skin = QVector3D(0.8F, 0.6F, 0.5F);
  62. palette.cloth = QVector3D(0.7F, 0.3F, 0.2F);
  63. palette.leather = QVector3D(0.4F, 0.3F, 0.2F);
  64. palette.leatherDark = QVector3D(0.3F, 0.2F, 0.1F);
  65. palette.metal = QVector3D(0.7F, 0.7F, 0.7F);
  66. palette.wood = QVector3D(0.5F, 0.3F, 0.2F);
  67. return palette;
  68. }
  69. } // namespace
  70. class HelmetRenderersTest : public ::testing::Test {
  71. protected:
  72. void SetUp() override {
  73. // Ensure built-in equipment is registered
  74. registerBuiltInEquipment();
  75. ctx = createTestContext();
  76. frames = createTestFrames();
  77. palette = createTestPalette();
  78. anim.inputs.time = 0.0F;
  79. anim.inputs.isMoving = false;
  80. anim.inputs.is_attacking = false;
  81. anim.inputs.isMelee = false;
  82. }
  83. DrawContext ctx;
  84. BodyFrames frames;
  85. HumanoidPalette palette;
  86. HumanoidAnimationContext anim;
  87. MockSubmitter submitter;
  88. };
  89. TEST_F(HelmetRenderersTest, MontefortinoHelmetRendersWithValidFrames) {
  90. MontefortinoHelmetRenderer helmet;
  91. helmet.render(ctx, frames, palette, anim, submitter);
  92. // Montefortino helmet should render multiple mesh components
  93. EXPECT_GT(submitter.mesh_count, 0);
  94. }
  95. TEST_F(HelmetRenderersTest, MontefortinoHelmetHandlesZeroHeadRadius) {
  96. MontefortinoHelmetRenderer helmet;
  97. frames.head.radius = 0.0F;
  98. helmet.render(ctx, frames, palette, anim, submitter);
  99. // Should not render anything when head radius is zero
  100. EXPECT_EQ(submitter.mesh_count, 0);
  101. }
  102. TEST_F(HelmetRenderersTest, HeadwrapRendersWithValidFrames) {
  103. HeadwrapRenderer headwrap;
  104. headwrap.render(ctx, frames, palette, anim, submitter);
  105. // Headwrap should render band, knot, and tail
  106. EXPECT_GT(submitter.mesh_count, 0);
  107. }
  108. TEST_F(HelmetRenderersTest, HeadwrapHandlesZeroHeadRadius) {
  109. HeadwrapRenderer headwrap;
  110. frames.head.radius = 0.0F;
  111. headwrap.render(ctx, frames, palette, anim, submitter);
  112. // Should not render anything when head radius is zero
  113. EXPECT_EQ(submitter.mesh_count, 0);
  114. }
  115. TEST_F(HelmetRenderersTest, HelmetsRegisteredInEquipmentRegistry) {
  116. auto &registry = EquipmentRegistry::instance();
  117. // Verify montefortino helmet is registered
  118. EXPECT_TRUE(registry.has(EquipmentCategory::Helmet, "montefortino"));
  119. auto montefortino = registry.get(EquipmentCategory::Helmet, "montefortino");
  120. ASSERT_NE(montefortino, nullptr);
  121. // Verify headwrap is registered
  122. EXPECT_TRUE(registry.has(EquipmentCategory::Helmet, "headwrap"));
  123. auto headwrap = registry.get(EquipmentCategory::Helmet, "headwrap");
  124. ASSERT_NE(headwrap, nullptr);
  125. }
  126. TEST_F(HelmetRenderersTest, MontefortinoHelmetFromRegistryRenders) {
  127. auto &registry = EquipmentRegistry::instance();
  128. auto helmet = registry.get(EquipmentCategory::Helmet, "montefortino");
  129. ASSERT_NE(helmet, nullptr);
  130. helmet->render(ctx, frames, palette, anim, submitter);
  131. EXPECT_GT(submitter.mesh_count, 0);
  132. }
  133. TEST_F(HelmetRenderersTest, HeadwrapFromRegistryRenders) {
  134. auto &registry = EquipmentRegistry::instance();
  135. auto headwrap = registry.get(EquipmentCategory::Helmet, "headwrap");
  136. ASSERT_NE(headwrap, nullptr);
  137. headwrap->render(ctx, frames, palette, anim, submitter);
  138. EXPECT_GT(submitter.mesh_count, 0);
  139. }
  140. TEST_F(HelmetRenderersTest, HelmetsUseHeadFrameCoordinates) {
  141. // Test that helmets use head frame's coordinate system
  142. frames.head.origin = QVector3D(1.0F, 2.0F, 3.0F);
  143. frames.head.right = QVector3D(0.0F, 1.0F, 0.0F); // Rotated frame
  144. frames.head.up = QVector3D(-1.0F, 0.0F, 0.0F);
  145. frames.head.forward = QVector3D(0.0F, 0.0F, 1.0F);
  146. frames.head.radius = 0.12F;
  147. MontefortinoHelmetRenderer helmet;
  148. MockSubmitter submitter1;
  149. helmet.render(ctx, frames, palette, anim, submitter1);
  150. // Helmet should still render even with rotated frame
  151. EXPECT_GT(submitter1.mesh_count, 0);
  152. HeadwrapRenderer headwrap;
  153. MockSubmitter submitter2;
  154. headwrap.render(ctx, frames, palette, anim, submitter2);
  155. EXPECT_GT(submitter2.mesh_count, 0);
  156. }