Browse Source

apply format

djeada 1 month ago
parent
commit
e9dde89c89
44 changed files with 429 additions and 631 deletions
  1. 4 2
      assets/shaders/horse_swordsman_carthage.vert
  2. 2 1
      assets/shaders/horse_swordsman_kingdom_of_iron.vert
  3. 2 1
      assets/shaders/horse_swordsman_roman_republic.vert
  4. 4 2
      assets/shaders/spearman_carthage.vert
  5. 2 1
      assets/shaders/spearman_roman_republic.vert
  6. 2 1
      assets/shaders/swordsman_carthage.vert
  7. 2 1
      assets/shaders/swordsman_roman_republic.vert
  8. 12 18
      render/entity/nations/carthage/archer_renderer.cpp
  9. 1 1
      render/entity/nations/carthage/horse_swordsman_renderer.cpp
  10. 1 1
      render/entity/nations/carthage/spearman_renderer.cpp
  11. 1 1
      render/entity/nations/carthage/swordsman_renderer.cpp
  12. 15 20
      render/entity/nations/kingdom/archer_renderer.cpp
  13. 2 2
      render/entity/nations/kingdom/horse_swordsman_renderer.cpp
  14. 2 2
      render/entity/nations/kingdom/spearman_renderer.cpp
  15. 2 2
      render/entity/nations/kingdom/swordsman_renderer.cpp
  16. 13 19
      render/entity/nations/roman/archer_renderer.cpp
  17. 1 1
      render/entity/nations/roman/horse_swordsman_renderer.cpp
  18. 1 1
      render/entity/nations/roman/spearman_renderer.cpp
  19. 1 1
      render/entity/nations/roman/swordsman_renderer.cpp
  20. 3 8
      render/equipment/helmets/headwrap.cpp
  21. 1 1
      render/equipment/helmets/headwrap.h
  22. 23 32
      render/equipment/helmets/kingdom_heavy_helmet.cpp
  23. 1 3
      render/equipment/helmets/kingdom_heavy_helmet.h
  24. 8 14
      render/equipment/helmets/kingdom_light_helmet.cpp
  25. 1 3
      render/equipment/helmets/kingdom_light_helmet.h
  26. 7 12
      render/equipment/helmets/montefortino_helmet.cpp
  27. 1 1
      render/equipment/helmets/montefortino_helmet.h
  28. 26 47
      render/equipment/helmets/roman_heavy_helmet.cpp
  29. 1 5
      render/equipment/helmets/roman_heavy_helmet.h
  30. 6 18
      render/equipment/helmets/roman_light_helmet.cpp
  31. 1 4
      render/equipment/helmets/roman_light_helmet.h
  32. 11 30
      render/equipment/register_equipment.cpp
  33. 46 51
      render/equipment/weapons/bow_renderer.cpp
  34. 6 6
      render/equipment/weapons/bow_renderer.h
  35. 21 25
      render/equipment/weapons/quiver_renderer.cpp
  36. 1 1
      render/equipment/weapons/quiver_renderer.h
  37. 38 69
      render/humanoid/pose_controller.cpp
  38. 5 72
      render/humanoid/pose_controller.h
  39. 10 14
      render/humanoid/rig.cpp
  40. 0 5
      render/humanoid/rig.h
  41. 18 17
      tests/render/body_frames_test.cpp
  42. 7 6
      tests/render/helmet_renderers_test.cpp
  43. 61 52
      tests/render/pose_controller_compatibility_test.cpp
  44. 56 57
      tests/render/pose_controller_test.cpp

+ 4 - 2
assets/shaders/horse_swordsman_carthage.vert

@@ -10,7 +10,8 @@ uniform mat4 u_model;
 out vec3 v_normal;
 out vec2 v_texCoord;
 out vec3 v_worldPos;
-out float v_armorLayer; // Distinguish armor pieces for Carthaginian Numidian cavalry
+out float
+    v_armorLayer; // Distinguish armor pieces for Carthaginian Numidian cavalry
 
 void main() {
   v_normal = mat3(transpose(inverse(u_model))) * a_normal;
@@ -18,7 +19,8 @@ void main() {
   v_worldPos = vec3(u_model * vec4(a_position, 1.0));
 
   // Detect armor layer based on Y position for Carthaginian Numidian cavalry
-  // Upper body (helmet) = 0, Torso (light armor/cloak) = 1, Lower (bare legs/horse) = 2
+  // Upper body (helmet) = 0, Torso (light armor/cloak) = 1, Lower (bare
+  // legs/horse) = 2
   if (v_worldPos.y > 1.5) {
     v_armorLayer = 0.0; // Bronze cap/no helmet region
   } else if (v_worldPos.y > 0.8) {

+ 2 - 1
assets/shaders/horse_swordsman_kingdom_of_iron.vert

@@ -18,7 +18,8 @@ void main() {
   v_worldPos = vec3(u_model * vec4(a_position, 1.0));
 
   // Detect armor layer based on Y position for Kingdom mounted knight
-  // Upper body (great helm) = 0, Torso (full plate) = 1, Lower (horse barding) = 2
+  // Upper body (great helm) = 0, Torso (full plate) = 1, Lower (horse barding)
+  // = 2
   if (v_worldPos.y > 1.5) {
     v_armorLayer = 0.0; // Kingdom great helm/aventail region
   } else if (v_worldPos.y > 0.8) {

+ 2 - 1
assets/shaders/horse_swordsman_roman_republic.vert

@@ -18,7 +18,8 @@ void main() {
   v_worldPos = vec3(u_model * vec4(a_position, 1.0));
 
   // Detect armor layer based on Y position for Roman equestrian cavalry
-  // Upper body (attic helmet) = 0, Torso (muscle cuirass) = 1, Lower (pteruges/horse) = 2
+  // Upper body (attic helmet) = 0, Torso (muscle cuirass) = 1, Lower
+  // (pteruges/horse) = 2
   if (v_worldPos.y > 1.5) {
     v_armorLayer = 0.0; // Attic/phrygian helmet region
   } else if (v_worldPos.y > 0.8) {

+ 4 - 2
assets/shaders/spearman_carthage.vert

@@ -10,7 +10,8 @@ uniform mat4 u_model;
 out vec3 v_normal;
 out vec2 v_texCoord;
 out vec3 v_worldPos;
-out float v_armorLayer; // Distinguish armor pieces for Carthaginian Libyan spearman
+out float
+    v_armorLayer; // Distinguish armor pieces for Carthaginian Libyan spearman
 
 void main() {
   v_normal = mat3(transpose(inverse(u_model))) * a_normal;
@@ -18,7 +19,8 @@ void main() {
   v_worldPos = vec3(u_model * vec4(a_position, 1.0));
 
   // Detect armor layer based on Y position for Carthaginian Libyan infantry
-  // Upper body (helmet) = 0, Torso (linothorax/captured) = 1, Lower (greaves/skirt) = 2
+  // Upper body (helmet) = 0, Torso (linothorax/captured) = 1, Lower
+  // (greaves/skirt) = 2
   if (v_worldPos.y > 1.5) {
     v_armorLayer = 0.0; // Captured helmet/Iberian style region
   } else if (v_worldPos.y > 0.8) {

+ 2 - 1
assets/shaders/spearman_roman_republic.vert

@@ -18,7 +18,8 @@ void main() {
   v_worldPos = vec3(u_model * vec4(a_position, 1.0));
 
   // Detect armor layer based on Y position for Roman republican hastati
-  // Upper body (montefortino) = 0, Torso (pectorale/mail) = 1, Lower (belt/pteruges) = 2
+  // Upper body (montefortino) = 0, Torso (pectorale/mail) = 1, Lower
+  // (belt/pteruges) = 2
   if (v_worldPos.y > 1.5) {
     v_armorLayer = 0.0; // Montefortino helmet region
   } else if (v_worldPos.y > 0.8) {

+ 2 - 1
assets/shaders/swordsman_carthage.vert

@@ -10,7 +10,8 @@ uniform mat4 u_model;
 out vec3 v_normal;
 out vec2 v_texCoord;
 out vec3 v_worldPos;
-out float v_armorLayer; // Distinguish armor pieces for Carthaginian sacred band swordsman
+out float v_armorLayer; // Distinguish armor pieces for Carthaginian sacred band
+                        // swordsman
 
 void main() {
   v_normal = mat3(transpose(inverse(u_model))) * a_normal;

+ 2 - 1
assets/shaders/swordsman_roman_republic.vert

@@ -10,7 +10,8 @@ uniform mat4 u_model;
 out vec3 v_normal;
 out vec2 v_texCoord;
 out vec3 v_worldPos;
-out float v_armorLayer; // Distinguish armor pieces for Roman legionary swordsman
+out float
+    v_armorLayer; // Distinguish armor pieces for Roman legionary swordsman
 
 void main() {
   v_normal = mat3(transpose(inverse(u_model))) * a_normal;

+ 12 - 18
render/entity/nations/carthage/archer_renderer.cpp

@@ -342,57 +342,52 @@ public:
       seed ^= uint32_t(reinterpret_cast<uintptr_t>(ctx.entity) & 0xFFFFFFFFU);
     }
 
-    // Get fletching color for quiver renderer
     auto tint = [&](float k) {
       return QVector3D(clamp01(team_tint.x() * k), clamp01(team_tint.y() * k),
                        clamp01(team_tint.z() * k));
     };
     QVector3D const fletch = tint(0.9F);
 
-    // Render quiver using equipment registry
     auto &registry = EquipmentRegistry::instance();
     auto quiver = registry.get(EquipmentCategory::Weapon, "quiver");
     if (quiver) {
-      // Configure quiver with appropriate colors
+
       QuiverRenderConfig quiver_config;
       quiver_config.fletching_color = fletch;
       quiver_config.quiver_radius = HP::HEAD_RADIUS * 0.45F;
-      
-      // Safe downcast - we know "quiver" is a QuiverRenderer
-      auto *quiver_renderer = dynamic_cast<QuiverRenderer*>(quiver.get());
+
+      auto *quiver_renderer = dynamic_cast<QuiverRenderer *>(quiver.get());
       if (quiver_renderer) {
         quiver_renderer->setConfig(quiver_config);
       }
-      
+
       quiver->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
     }
 
-    // Render bow using equipment registry
     auto bow = registry.get(EquipmentCategory::Weapon, "bow_carthage");
     if (bow) {
-      // Configure Carthaginian composite recurve bow
+
       BowRenderConfig bow_config;
       bow_config.string_color = QVector3D(0.30F, 0.30F, 0.32F);
-      bow_config.metal_color = Render::Geom::clampVec01(v.palette.metal * 1.15F);
+      bow_config.metal_color =
+          Render::Geom::clampVec01(v.palette.metal * 1.15F);
       bow_config.fletching_color = fletch;
       bow_config.bow_top_y = HP::SHOULDER_Y + 0.55F;
       bow_config.bow_bot_y = HP::WAIST_Y - 0.25F;
       bow_config.bow_x = 0.0F;
-      
-      // Apply style overrides if available
+
       if (style.bow_string_color) {
         bow_config.string_color = saturate_color(*style.bow_string_color);
       }
       if (style.fletching_color) {
         bow_config.fletching_color = saturate_color(*style.fletching_color);
       }
-      
-      // Safe downcast - we know "bow" is a BowRenderer
-      auto *bow_renderer = dynamic_cast<BowRenderer*>(bow.get());
+
+      auto *bow_renderer = dynamic_cast<BowRenderer *>(bow.get());
       if (bow_renderer) {
         bow_renderer->setConfig(bow_config);
       }
-      
+
       bow->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
     }
   }
@@ -407,7 +402,7 @@ public:
 
     if (!style.show_helmet) {
       if (style.attachment_profile == std::string(k_attachment_headwrap)) {
-        // Use headwrap helmet from equipment registry
+
         auto headwrap = registry.get(EquipmentCategory::Helmet, "headwrap");
         if (headwrap) {
           headwrap->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
@@ -416,7 +411,6 @@ public:
       return;
     }
 
-    // Use montefortino helmet from equipment registry
     auto helmet = registry.get(EquipmentCategory::Helmet, "montefortino");
     if (helmet) {
       helmet->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);

+ 1 - 1
render/entity/nations/carthage/horse_swordsman_renderer.cpp

@@ -275,7 +275,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use montefortino helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "montefortino");
     if (helmet) {

+ 1 - 1
render/entity/nations/carthage/spearman_renderer.cpp

@@ -264,7 +264,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use montefortino helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "montefortino");
     if (helmet) {

+ 1 - 1
render/entity/nations/carthage/swordsman_renderer.cpp

@@ -213,7 +213,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use montefortino helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "montefortino");
     if (helmet) {

+ 15 - 20
render/entity/nations/kingdom/archer_renderer.cpp

@@ -264,65 +264,60 @@ public:
 
     auto const &style = resolve_style(ctx);
     QVector3D team_tint = resolveTeamTint(ctx);
-    
-    // Get fletching color for quiver renderer
+
     auto tint = [&](float k) {
       return QVector3D(clamp01(team_tint.x() * k), clamp01(team_tint.y() * k),
                        clamp01(team_tint.z() * k));
     };
     QVector3D const fletch = tint(0.9F);
 
-    // Render quiver using equipment registry
     auto &registry = EquipmentRegistry::instance();
     auto quiver = registry.get(EquipmentCategory::Weapon, "quiver");
     if (quiver) {
-      // Configure quiver with appropriate colors
+
       QuiverRenderConfig quiver_config;
       quiver_config.fletching_color = fletch;
       quiver_config.quiver_radius = HP::HEAD_RADIUS * 0.45F;
-      
-      // Safe downcast - we know "quiver" is a QuiverRenderer
-      auto *quiver_renderer = dynamic_cast<QuiverRenderer*>(quiver.get());
+
+      auto *quiver_renderer = dynamic_cast<QuiverRenderer *>(quiver.get());
       if (quiver_renderer) {
         quiver_renderer->setConfig(quiver_config);
       }
-      
+
       quiver->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
     }
 
-    // Render bow using equipment registry
     auto bow = registry.get(EquipmentCategory::Weapon, "bow_kingdom");
     if (bow) {
-      // Configure Kingdom/European longbow (taller, straighter)
+
       BowRenderConfig bow_config;
       bow_config.string_color = QVector3D(0.30F, 0.30F, 0.32F);
-      bow_config.metal_color = Render::Geom::clampVec01(v.palette.metal * 1.15F);
+      bow_config.metal_color =
+          Render::Geom::clampVec01(v.palette.metal * 1.15F);
       bow_config.fletching_color = fletch;
-      bow_config.bow_top_y = HP::SHOULDER_Y + 0.55F;   // Same as original
-      bow_config.bow_bot_y = HP::WAIST_Y - 0.25F;      // Same as original
+      bow_config.bow_top_y = HP::SHOULDER_Y + 0.55F;
+      bow_config.bow_bot_y = HP::WAIST_Y - 0.25F;
       bow_config.bow_x = 0.0F;
-      
-      // Apply style overrides if available
+
       if (style.bow_string_color) {
         bow_config.string_color = saturate_color(*style.bow_string_color);
       }
       if (style.fletching_color) {
         bow_config.fletching_color = saturate_color(*style.fletching_color);
       }
-      
-      // Safe downcast - we know "bow" is a BowRenderer
-      auto *bow_renderer = dynamic_cast<BowRenderer*>(bow.get());
+
+      auto *bow_renderer = dynamic_cast<BowRenderer *>(bow.get());
       if (bow_renderer) {
         bow_renderer->setConfig(bow_config);
       }
-      
+
       bow->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
     }
   }
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Kingdom Light helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "kingdom_light");
     if (helmet) {

+ 2 - 2
render/entity/nations/kingdom/horse_swordsman_renderer.cpp

@@ -22,13 +22,13 @@
 #include <qvectornd.h>
 #include <unordered_map>
 
+#include "../../../equipment/equipment_registry.h"
 #include <QMatrix4x4>
 #include <QString>
 #include <QVector3D>
 #include <algorithm>
 #include <cmath>
 #include <cstdint>
-#include "../../../equipment/equipment_registry.h"
 
 namespace Render::GL::Kingdom {
 
@@ -275,7 +275,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Kingdom Heavy helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "kingdom_heavy");
     if (helmet) {

+ 2 - 2
render/entity/nations/kingdom/spearman_renderer.cpp

@@ -17,6 +17,7 @@
 #include "../../renderer_constants.h"
 #include "spearman_style.h"
 
+#include "../../../equipment/equipment_registry.h"
 #include <QMatrix4x4>
 #include <QString>
 #include <QVector3D>
@@ -29,7 +30,6 @@
 #include <string>
 #include <string_view>
 #include <unordered_map>
-#include "../../../equipment/equipment_registry.h"
 
 namespace Render::GL::Kingdom {
 
@@ -264,7 +264,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Kingdom heavy helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "kingdom_heavy");
     if (helmet) {

+ 2 - 2
render/entity/nations/kingdom/swordsman_renderer.cpp

@@ -22,6 +22,7 @@
 #include <qvectornd.h>
 #include <unordered_map>
 
+#include "../../../equipment/equipment_registry.h"
 #include <QMatrix4x4>
 #include <QString>
 #include <QVector3D>
@@ -31,7 +32,6 @@
 #include <optional>
 #include <string>
 #include <string_view>
-#include "../../../equipment/equipment_registry.h"
 
 namespace Render::GL::Kingdom {
 
@@ -213,7 +213,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Kingdom Heavy helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "kingdom_heavy");
     if (helmet) {

+ 13 - 19
render/entity/nations/roman/archer_renderer.cpp

@@ -264,58 +264,53 @@ public:
 
     auto const &style = resolve_style(ctx);
     QVector3D team_tint = resolveTeamTint(ctx);
-    
-    // Get fletching color for quiver renderer
+
     auto tint = [&](float k) {
       return QVector3D(clamp01(team_tint.x() * k), clamp01(team_tint.y() * k),
                        clamp01(team_tint.z() * k));
     };
     QVector3D const fletch = tint(0.9F);
 
-    // Render quiver using equipment registry
     auto &registry = EquipmentRegistry::instance();
     auto quiver = registry.get(EquipmentCategory::Weapon, "quiver");
     if (quiver) {
-      // Configure quiver with appropriate colors
+
       QuiverRenderConfig quiver_config;
       quiver_config.fletching_color = fletch;
       quiver_config.quiver_radius = HP::HEAD_RADIUS * 0.45F;
-      
-      // Safe downcast - we know "quiver" is a QuiverRenderer
-      auto *quiver_renderer = dynamic_cast<QuiverRenderer*>(quiver.get());
+
+      auto *quiver_renderer = dynamic_cast<QuiverRenderer *>(quiver.get());
       if (quiver_renderer) {
         quiver_renderer->setConfig(quiver_config);
       }
-      
+
       quiver->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
     }
 
-    // Render bow using equipment registry
     auto bow = registry.get(EquipmentCategory::Weapon, "bow_roman");
     if (bow) {
-      // Configure Roman simple self bow (moderate curve, standard size)
+
       BowRenderConfig bow_config;
       bow_config.string_color = QVector3D(0.30F, 0.30F, 0.32F);
-      bow_config.metal_color = Render::Geom::clampVec01(v.palette.metal * 1.15F);
+      bow_config.metal_color =
+          Render::Geom::clampVec01(v.palette.metal * 1.15F);
       bow_config.fletching_color = fletch;
       bow_config.bow_top_y = HP::SHOULDER_Y + 0.55F;
       bow_config.bow_bot_y = HP::WAIST_Y - 0.25F;
       bow_config.bow_x = 0.0F;
-      
-      // Apply style overrides if available
+
       if (style.bow_string_color) {
         bow_config.string_color = saturate_color(*style.bow_string_color);
       }
       if (style.fletching_color) {
         bow_config.fletching_color = saturate_color(*style.fletching_color);
       }
-      
-      // Safe downcast - we know "bow" is a BowRenderer
-      auto *bow_renderer = dynamic_cast<BowRenderer*>(bow.get());
+
+      auto *bow_renderer = dynamic_cast<BowRenderer *>(bow.get());
       if (bow_renderer) {
         bow_renderer->setConfig(bow_config);
       }
-      
+
       bow->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
     }
   }
@@ -330,7 +325,7 @@ public:
 
     if (!style.show_helmet) {
       if (style.attachment_profile == std::string(k_attachment_headwrap)) {
-        // Use headwrap helmet from equipment registry
+
         auto headwrap = registry.get(EquipmentCategory::Helmet, "headwrap");
         if (headwrap) {
           headwrap->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);
@@ -339,7 +334,6 @@ public:
       return;
     }
 
-    // Use Roman light helmet from equipment registry
     auto helmet = registry.get(EquipmentCategory::Helmet, "roman_light");
     if (helmet) {
       helmet->render(ctx, pose.bodyFrames, v.palette, anim_ctx, out);

+ 1 - 1
render/entity/nations/roman/horse_swordsman_renderer.cpp

@@ -275,7 +275,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Roman heavy helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "roman_heavy");
     if (helmet) {

+ 1 - 1
render/entity/nations/roman/spearman_renderer.cpp

@@ -264,7 +264,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Roman heavy helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "roman_heavy");
     if (helmet) {

+ 1 - 1
render/entity/nations/roman/swordsman_renderer.cpp

@@ -213,7 +213,7 @@ public:
 
   void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
-    // Use Roman heavy helmet from equipment registry
+
     auto &registry = EquipmentRegistry::instance();
     auto helmet = registry.get(EquipmentCategory::Helmet, "roman_heavy");
     if (helmet) {

+ 3 - 8
render/equipment/helmets/headwrap.cpp

@@ -17,7 +17,7 @@ void HeadwrapRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
                               const HumanoidPalette &palette,
                               const HumanoidAnimationContext &anim,
                               ISubmitter &submitter) {
-  (void)anim; // Unused
+  (void)anim;
 
   QVector3D const cloth_color =
       saturate_color(palette.cloth * QVector3D(0.9F, 1.05F, 1.05F));
@@ -31,29 +31,24 @@ void HeadwrapRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
     return HumanoidRendererBase::frameLocalPosition(head, normalized);
   };
 
-  // Main headwrap band
   QVector3D const band_top = headPoint(QVector3D(0.0F, 0.70F, 0.0F));
   QVector3D const band_bot = headPoint(QVector3D(0.0F, 0.30F, 0.0F));
   submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, band_bot, band_top,
-                                 head_r * 1.08F),
+                 cylinderBetween(ctx.model, band_bot, band_top, head_r * 1.08F),
                  cloth_color, nullptr, 1.0F);
 
-  // Knot on the side
   QVector3D const knot_center = headPoint(QVector3D(0.10F, 0.60F, 0.72F));
   QMatrix4x4 knot_m = ctx.model;
   knot_m.translate(knot_center);
   knot_m.scale(head_r * 0.32F);
   submitter.mesh(getUnitSphere(), knot_m, cloth_color * 1.05F, nullptr, 1.0F);
 
-  // Hanging tail
   QVector3D const tail_top = knot_center + head.right * (-0.08F) +
                              head.up * (-0.05F) + head.forward * (-0.06F);
   QVector3D const tail_bot = tail_top + head.right * 0.02F +
                              head.up * (-0.28F) + head.forward * (-0.08F);
   submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, tail_top, tail_bot,
-                                 head_r * 0.28F),
+                 cylinderBetween(ctx.model, tail_top, tail_bot, head_r * 0.28F),
                  cloth_color * QVector3D(0.92F, 0.98F, 1.05F), nullptr, 1.0F);
 }
 

+ 1 - 1
render/equipment/helmets/headwrap.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 
 namespace Render::GL {
 

+ 23 - 32
render/equipment/helmets/kingdom_heavy_helmet.cpp

@@ -19,7 +19,7 @@ void KingdomHeavyHelmetRenderer::render(const DrawContext &ctx,
                                         const HumanoidPalette &palette,
                                         const HumanoidAnimationContext &anim,
                                         ISubmitter &submitter) {
-  (void)anim; // Unused
+  (void)anim;
 
   const AttachmentFrame &head = frames.head;
   float const head_r = head.radius;
@@ -31,7 +31,6 @@ void KingdomHeavyHelmetRenderer::render(const DrawContext &ctx,
     return HumanoidRendererBase::frameLocalPosition(head, normalized);
   };
 
-  // Great helm steel colors
   QVector3D const steel_color =
       saturate_color(palette.metal * QVector3D(0.95F, 0.96F, 1.0F));
   QVector3D const brass_color =
@@ -41,7 +40,6 @@ void KingdomHeavyHelmetRenderer::render(const DrawContext &ctx,
   float const helm_r = head_r * 1.15F;
   float const helm_ratio = helm_r / head_r;
 
-  // Main enclosed helm body
   QVector3D const helm_bot = headPoint(QVector3D(0.0F, -0.20F, 0.0F));
   QVector3D const helm_top = headPoint(QVector3D(0.0F, 1.40F, 0.0F));
 
@@ -49,28 +47,25 @@ void KingdomHeavyHelmetRenderer::render(const DrawContext &ctx,
                  cylinderBetween(ctx.model, helm_bot, helm_top, helm_r),
                  steel_color, nullptr, 1.0F);
 
-  // Flat top (characteristic of great helm)
   QVector3D const cap_top = headPoint(QVector3D(0.0F, 1.48F, 0.0F));
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, helm_top, cap_top, helm_r * 0.98F),
                  steel_color * 1.05F, nullptr, 1.0F);
 
-  // Decorative reinforcement bands
   auto ring = [&](float y_offset, float radius_scale, const QVector3D &col) {
     QVector3D const center = headPoint(QVector3D(0.0F, y_offset, 0.0F));
     float const height = head_r * 0.015F;
     QVector3D const a = center + head.up * (height * 0.5F);
     QVector3D const b = center - head.up * (height * 0.5F);
     submitter.mesh(getUnitCylinder(),
-                   cylinderBetween(ctx.model, a, b, helm_r * radius_scale),
-                   col, nullptr, 1.0F);
+                   cylinderBetween(ctx.model, a, b, helm_r * radius_scale), col,
+                   nullptr, 1.0F);
   };
 
   ring(1.25F, 1.02F, steel_color * 1.08F);
   ring(0.50F, 1.02F, steel_color * 1.08F);
   ring(-0.05F, 1.02F, steel_color * 1.08F);
 
-  // Eye slit (horizontal bar)
   float const visor_y = 0.15F;
   float const visor_forward = helm_r * 0.72F;
   float const visor_forward_norm = visor_forward / head_r;
@@ -79,20 +74,18 @@ void KingdomHeavyHelmetRenderer::render(const DrawContext &ctx,
 
   QVector3D const visor_hl = visor_center - head.right * (helm_r * 0.35F);
   QVector3D const visor_hr = visor_center + head.right * (helm_r * 0.35F);
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, visor_hl, visor_hr,
-                                 head_r * 0.012F),
-                 visor_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, visor_hl, visor_hr, head_r * 0.012F),
+      visor_color, nullptr, 1.0F);
 
-  // Vertical nose guard
   QVector3D const visor_vt = visor_center + head.up * (helm_r * 0.25F);
   QVector3D const visor_vb = visor_center - head.up * (helm_r * 0.25F);
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, visor_vb, visor_vt,
-                                 head_r * 0.012F),
-                 visor_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, visor_vb, visor_vt, head_r * 0.012F),
+      visor_color, nullptr, 1.0F);
 
-  // Breathing holes (arranged in cross pattern)
   auto draw_breathing_hole = [&](float x_norm, float y_norm) {
     QVector3D const pos = headPoint(
         QVector3D(x_norm * helm_ratio, y_norm, visor_forward_norm * 0.97F));
@@ -107,33 +100,31 @@ void KingdomHeavyHelmetRenderer::render(const DrawContext &ctx,
     draw_breathing_hole(-0.50F, 0.05F - i * 0.10F);
   }
 
-  // Heraldic cross on top (brass)
   QVector3D const top_center = headPoint(QVector3D(0.0F, 1.45F, 0.0F));
 
   QVector3D const cross_h1 = top_center - head.right * 0.05F;
   QVector3D const cross_h2 = top_center + head.right * 0.05F;
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, cross_h1, cross_h2,
-                                 head_r * 0.010F),
-                 brass_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, cross_h1, cross_h2, head_r * 0.010F),
+      brass_color, nullptr, 1.0F);
 
   QVector3D const cross_v1 = top_center - head.forward * 0.05F;
   QVector3D const cross_v2 = top_center + head.forward * 0.05F;
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, cross_v1, cross_v2,
-                                 head_r * 0.010F),
-                 brass_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, cross_v1, cross_v2, head_r * 0.010F),
+      brass_color, nullptr, 1.0F);
 
-  // Face plate edge (slightly forward from main helm)
   float const face_forward = helm_r * 0.68F;
   QVector3D const face_top =
       headPoint(QVector3D(0.0F, 0.40F, face_forward / head_r));
   QVector3D const face_bot =
       headPoint(QVector3D(0.0F, -0.15F, face_forward / head_r));
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, face_bot, face_top,
-                                 head_r * 0.015F),
-                 steel_color * 1.08F, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, face_bot, face_top, head_r * 0.015F),
+      steel_color * 1.08F, nullptr, 1.0F);
 }
 
 } // namespace Render::GL

+ 1 - 3
render/equipment/helmets/kingdom_heavy_helmet.h

@@ -1,13 +1,11 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 
 namespace Render::GL {
 
-// Kingdom heavy helmet - great helm style for knights and heavy infantry
-// Features enclosed design with eye slits and breathing holes
 class KingdomHeavyHelmetRenderer : public IEquipmentRenderer {
 public:
   KingdomHeavyHelmetRenderer() = default;

+ 8 - 14
render/equipment/helmets/kingdom_light_helmet.cpp

@@ -18,7 +18,7 @@ void KingdomLightHelmetRenderer::render(const DrawContext &ctx,
                                         const HumanoidPalette &palette,
                                         const HumanoidAnimationContext &anim,
                                         ISubmitter &submitter) {
-  (void)anim; // Unused
+  (void)anim;
 
   const AttachmentFrame &head = frames.head;
   float const head_r = head.radius;
@@ -30,7 +30,6 @@ void KingdomLightHelmetRenderer::render(const DrawContext &ctx,
     return HumanoidRendererBase::frameLocalPosition(head, normalized);
   };
 
-  // Kettle hat steel colors
   QVector3D const steel_color =
       saturate_color(palette.metal * QVector3D(0.88F, 0.90F, 0.95F));
   QVector3D const steel_dark = steel_color * 0.82F;
@@ -38,7 +37,6 @@ void KingdomLightHelmetRenderer::render(const DrawContext &ctx,
   float const bowl_scale = 1.06F;
   float const bowl_r = head_r * bowl_scale;
 
-  // Main bowl
   QVector3D const bowl_top = headPoint(QVector3D(0.0F, 1.10F, 0.0F));
   QVector3D const bowl_bot = headPoint(QVector3D(0.0F, 0.15F, 0.0F));
 
@@ -46,43 +44,39 @@ void KingdomLightHelmetRenderer::render(const DrawContext &ctx,
                  cylinderBetween(ctx.model, bowl_bot, bowl_top, bowl_r),
                  steel_color, nullptr, 1.0F);
 
-  // Rounded top cap
   QMatrix4x4 cap_m = ctx.model;
   cap_m.translate(bowl_top);
   cap_m.scale(bowl_r * 0.92F, head_r * 0.28F, bowl_r * 0.92F);
   submitter.mesh(getUnitSphere(), cap_m, steel_color * 1.05F, nullptr, 1.0F);
 
-  // Wide brim (characteristic kettle hat feature)
   QVector3D const brim_top = headPoint(QVector3D(0.0F, 0.18F, 0.0F));
   QVector3D const brim_bot = headPoint(QVector3D(0.0F, 0.08F, 0.0F));
-  float const brim_r = head_r * 1.42F; // Wide brim for protection
+  float const brim_r = head_r * 1.42F;
 
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, brim_bot, brim_top, brim_r),
                  steel_dark, nullptr, 1.0F);
 
-  // Reinforcement rings on bowl
   auto ring = [&](float y_offset, float radius_scale, const QVector3D &col) {
     QVector3D const center = headPoint(QVector3D(0.0F, y_offset, 0.0F));
     float const height = head_r * 0.010F;
     QVector3D const a = center + head.up * (height * 0.5F);
     QVector3D const b = center - head.up * (height * 0.5F);
     submitter.mesh(getUnitCylinder(),
-                   cylinderBetween(ctx.model, a, b, bowl_r * radius_scale),
-                   col, nullptr, 1.0F);
+                   cylinderBetween(ctx.model, a, b, bowl_r * radius_scale), col,
+                   nullptr, 1.0F);
   };
 
   ring(0.90F, 1.01F, steel_color * 1.05F);
   ring(0.50F, 1.01F, steel_color * 1.05F);
   ring(0.20F, 1.01F, steel_color * 1.05F);
 
-  // Brim edge reinforcement
   QVector3D const brim_edge_top = headPoint(QVector3D(0.0F, 0.09F, 0.0F));
   QVector3D const brim_edge_bot = headPoint(QVector3D(0.0F, 0.07F, 0.0F));
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, brim_edge_bot, brim_edge_top,
-                                 brim_r * 1.01F),
-                 steel_color * 1.08F, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, brim_edge_bot, brim_edge_top, brim_r * 1.01F),
+      steel_color * 1.08F, nullptr, 1.0F);
 }
 
 } // namespace Render::GL

+ 1 - 3
render/equipment/helmets/kingdom_light_helmet.h

@@ -1,13 +1,11 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 
 namespace Render::GL {
 
-// Kingdom light helmet - kettle hat style with wide brim
-// Used by archers and light infantry for protection from arrows
 class KingdomLightHelmetRenderer : public IEquipmentRenderer {
 public:
   KingdomLightHelmetRenderer() = default;

+ 7 - 12
render/equipment/helmets/montefortino_helmet.cpp

@@ -21,7 +21,7 @@ void MontefortinoHelmetRenderer::render(const DrawContext &ctx,
                                         const HumanoidPalette &palette,
                                         const HumanoidAnimationContext &anim,
                                         ISubmitter &submitter) {
-  (void)anim; // Unused
+  (void)anim;
 
   const AttachmentFrame &head = frames.head;
   float const head_r = head.radius;
@@ -47,10 +47,9 @@ void MontefortinoHelmetRenderer::render(const DrawContext &ctx,
   QVector3D leather_band =
       saturate_color(palette.leatherDark * QVector3D(1.10F, 0.96F, 0.80F));
 
-  // Draw leather cap
   auto draw_leather_cap = [&]() {
-    QVector3D leather_brown = saturate_color(palette.leatherDark *
-                                             QVector3D(1.15F, 0.95F, 0.78F));
+    QVector3D leather_brown =
+        saturate_color(palette.leatherDark * QVector3D(1.15F, 0.95F, 0.78F));
     QVector3D leather_dark =
         saturate_color(leather_brown * QVector3D(0.85F, 0.88F, 0.92F));
     QVector3D bronze_stud =
@@ -65,10 +64,10 @@ void MontefortinoHelmetRenderer::render(const DrawContext &ctx,
     QVector3D const band_top = headPoint(QVector3D(0.0F, 0.20F, 0.0F));
     QVector3D const band_bot = headPoint(QVector3D(0.0F, 0.15F, 0.0F));
 
-    submitter.mesh(getUnitCylinder(),
-                   cylinderBetween(ctx.model, band_bot, band_top,
-                                   head_r * 1.02F),
-                   leather_dark, nullptr, 1.0F);
+    submitter.mesh(
+        getUnitCylinder(),
+        cylinderBetween(ctx.model, band_bot, band_top, head_r * 1.02F),
+        leather_dark, nullptr, 1.0F);
 
     auto draw_stud = [&](float angle) {
       QVector3D const stud_pos = headPoint(
@@ -86,11 +85,9 @@ void MontefortinoHelmetRenderer::render(const DrawContext &ctx,
 
   draw_leather_cap();
 
-  // Top knob
   QMatrix4x4 top_knob = headTransform(QVector3D(0.0F, 0.88F, 0.0F), 0.18F);
   submitter.mesh(getUnitSphere(), top_knob, tinned_highlight, nullptr, 1.0F);
 
-  // Brow band
   QVector3D const brow_top = headPoint(QVector3D(0.0F, 0.55F, 0.0F));
   QVector3D const brow_bot = headPoint(QVector3D(0.0F, 0.42F, 0.0F));
   QMatrix4x4 brow =
@@ -98,7 +95,6 @@ void MontefortinoHelmetRenderer::render(const DrawContext &ctx,
   brow.scale(1.04F, 1.0F, 0.86F);
   submitter.mesh(getUnitCylinder(), brow, leather_band, nullptr, 1.0F);
 
-  // Rim
   QVector3D const rim_upper = headPoint(QVector3D(0.0F, 0.40F, 0.0F));
   QVector3D const rim_lower = headPoint(QVector3D(0.0F, 0.30F, 0.0F));
   QMatrix4x4 rim =
@@ -107,7 +103,6 @@ void MontefortinoHelmetRenderer::render(const DrawContext &ctx,
   submitter.mesh(getUnitCylinder(), rim,
                  bronze * QVector3D(0.94F, 0.92F, 0.88F), nullptr, 1.0F);
 
-  // Crest
   QVector3D const crest_front = headPoint(QVector3D(0.0F, 0.92F, 0.82F));
   QVector3D const crest_back = headPoint(QVector3D(0.0F, 0.92F, -0.90F));
   QMatrix4x4 crest =

+ 1 - 1
render/equipment/helmets/montefortino_helmet.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 
 namespace Render::GL {
 

+ 26 - 47
render/equipment/helmets/roman_heavy_helmet.cpp

@@ -20,7 +20,7 @@ void RomanHeavyHelmetRenderer::render(const DrawContext &ctx,
                                       const HumanoidPalette &palette,
                                       const HumanoidAnimationContext &anim,
                                       ISubmitter &submitter) {
-  (void)anim; // Unused
+  (void)anim;
 
   const AttachmentFrame &head = frames.head;
   float const head_r = head.radius;
@@ -32,7 +32,6 @@ void RomanHeavyHelmetRenderer::render(const DrawContext &ctx,
     return HumanoidRendererBase::frameLocalPosition(head, normalized);
   };
 
-  // Imperial Gallic helmet colors (steel with bronze/brass accents)
   QVector3D const steel_color =
       saturate_color(palette.metal * QVector3D(0.95F, 0.96F, 1.0F));
   QVector3D const brass_color =
@@ -42,7 +41,6 @@ void RomanHeavyHelmetRenderer::render(const DrawContext &ctx,
   float const helm_r = head_r * 1.15F;
   float const helm_ratio = helm_r / head_r;
 
-  // Main bowl (rounded dome)
   QVector3D const helm_bot = headPoint(QVector3D(0.0F, -0.20F, 0.0F));
   QVector3D const helm_top = headPoint(QVector3D(0.0F, 1.40F, 0.0F));
 
@@ -50,13 +48,11 @@ void RomanHeavyHelmetRenderer::render(const DrawContext &ctx,
                  cylinderBetween(ctx.model, helm_bot, helm_top, helm_r),
                  steel_color, nullptr, 1.0F);
 
-  // Top cap
   QVector3D const cap_top = headPoint(QVector3D(0.0F, 1.48F, 0.0F));
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, helm_top, cap_top, helm_r * 0.98F),
                  steel_color * 1.05F, nullptr, 1.0F);
 
-  // Decorative reinforcement rings
   auto ring = [&](float y_offset, const QVector3D &col) {
     QVector3D const center = headPoint(QVector3D(0.0F, y_offset, 0.0F));
     float const height = head_r * 0.015F;
@@ -71,43 +67,36 @@ void RomanHeavyHelmetRenderer::render(const DrawContext &ctx,
   ring(0.50F, steel_color * 1.08F);
   ring(-0.05F, steel_color * 1.08F);
 
-  // Reinforced brow ridge
   QVector3D const brow_center = headPoint(QVector3D(0.0F, 0.15F, 0.0F));
   QVector3D const brow_top = brow_center + head.up * 0.03F;
   QVector3D const brow_bot = brow_center - head.up * 0.02F;
   submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, brow_bot, brow_top,
-                                 helm_r * 1.08F),
+                 cylinderBetween(ctx.model, brow_bot, brow_top, helm_r * 1.08F),
                  brass_color * 0.95F, nullptr, 1.0F);
 
-  // Visor cross (face protection)
   float const visor_y = 0.15F;
   float const visor_forward = helm_r * 0.72F;
   float const visor_forward_norm = visor_forward / head_r;
   QVector3D const visor_center =
       headPoint(QVector3D(0.0F, visor_y, visor_forward_norm));
 
-  // Horizontal visor bar
   QVector3D const visor_hl = visor_center - head.right * (helm_r * 0.35F);
   QVector3D const visor_hr = visor_center + head.right * (helm_r * 0.35F);
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, visor_hl, visor_hr,
-                                 head_r * 0.012F),
-                 visor_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, visor_hl, visor_hr, head_r * 0.012F),
+      visor_color, nullptr, 1.0F);
 
-  // Vertical visor bar
   QVector3D const visor_vt = visor_center + head.up * (helm_r * 0.25F);
   QVector3D const visor_vb = visor_center - head.up * (helm_r * 0.25F);
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, visor_vb, visor_vt,
-                                 head_r * 0.012F),
-                 visor_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, visor_vb, visor_vt, head_r * 0.012F),
+      visor_color, nullptr, 1.0F);
 
-  // Breathing holes (4 on each side)
   auto draw_breathing_hole = [&](float x_sign, float y_offset) {
-    QVector3D const pos = headPoint(
-        QVector3D(x_sign * 0.50F * helm_ratio, y_offset,
-                  visor_forward_norm * 0.97F));
+    QVector3D const pos = headPoint(QVector3D(
+        x_sign * 0.50F * helm_ratio, y_offset, visor_forward_norm * 0.97F));
     QMatrix4x4 m = ctx.model;
     m.translate(pos);
     m.scale(0.010F);
@@ -119,73 +108,63 @@ void RomanHeavyHelmetRenderer::render(const DrawContext &ctx,
     draw_breathing_hole(-1.0F, 0.05F - i * 0.10F);
   }
 
-  // Decorative brass cross on forehead
   QVector3D const cross_center =
       headPoint(QVector3D(0.0F, 0.60F, (helm_r * 0.75F) / head_r));
 
   QVector3D const cross_h1 = cross_center - head.right * 0.04F;
   QVector3D const cross_h2 = cross_center + head.right * 0.04F;
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, cross_h1, cross_h2,
-                                 head_r * 0.008F),
-                 brass_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, cross_h1, cross_h2, head_r * 0.008F),
+      brass_color, nullptr, 1.0F);
 
   QVector3D const cross_v1 = cross_center - head.up * 0.04F;
   QVector3D const cross_v2 = cross_center + head.up * 0.04F;
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, cross_v1, cross_v2,
-                                 head_r * 0.008F),
-                 brass_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, cross_v1, cross_v2, head_r * 0.008F),
+      brass_color, nullptr, 1.0F);
 
-  // Cheek guards (hinged protection for face)
   float const cheek_w = head_r * 0.52F;
   QVector3D const cheek_top = headPoint(QVector3D(0.0F, 0.18F, 0.0F));
   QVector3D const cheek_bot = headPoint(QVector3D(0.0F, -0.45F, 0.0F));
 
-  // Left cheek guard
   QVector3D const cheek_ltop =
       cheek_top + head.right * (-cheek_w / head_r) + head.forward * 0.42F;
   QVector3D const cheek_lbot = cheek_bot +
-                                head.right * (-cheek_w * 0.85F / head_r) +
-                                head.forward * 0.32F;
+                               head.right * (-cheek_w * 0.85F / head_r) +
+                               head.forward * 0.32F;
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, cheek_lbot, cheek_ltop, 0.032F),
                  steel_color * 0.94F, nullptr, 1.0F);
 
-  // Right cheek guard
   QVector3D const cheek_rtop =
       cheek_top + head.right * (cheek_w / head_r) + head.forward * 0.42F;
-  QVector3D const cheek_rbot =
-      cheek_bot + head.right * (cheek_w * 0.85F / head_r) +
-      head.forward * 0.32F;
+  QVector3D const cheek_rbot = cheek_bot +
+                               head.right * (cheek_w * 0.85F / head_r) +
+                               head.forward * 0.32F;
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, cheek_rbot, cheek_rtop, 0.032F),
                  steel_color * 0.94F, nullptr, 1.0F);
 
-  // Neck guard (back of helmet)
   QVector3D const neck_top = headPoint(QVector3D(0.0F, -0.10F, -1.02F));
   QVector3D const neck_bot = headPoint(QVector3D(0.0F, -0.28F, -0.95F));
   submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, neck_bot, neck_top,
-                                 helm_r * 0.95F),
+                 cylinderBetween(ctx.model, neck_bot, neck_top, helm_r * 0.95F),
                  steel_color * 0.92F, nullptr, 1.0F);
 
-  // Plume/crest for identification (officer's crest)
   QVector3D const crest_base = cap_top;
   QVector3D const crest_mid = crest_base + head.up * 0.08F;
   QVector3D const crest_top = crest_mid + head.up * 0.15F;
 
-  // Crest holder (brass)
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, crest_base, crest_mid, 0.020F),
                  brass_color, nullptr, 1.0F);
 
-  // Plume (red - traditional Roman officer color)
   submitter.mesh(getUnitCone(),
                  coneFromTo(ctx.model, crest_mid, crest_top, 0.048F),
                  QVector3D(0.92F, 0.15F, 0.15F), nullptr, 1.0F);
 
-  // Plume ornament (brass ball)
   submitter.mesh(getUnitSphere(), sphereAt(ctx.model, crest_top, 0.022F),
                  brass_color, nullptr, 1.0F);
 }

+ 1 - 5
render/equipment/helmets/roman_heavy_helmet.h

@@ -1,15 +1,11 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 
 namespace Render::GL {
 
-// Roman heavy helmet - Imperial Gallic style galea for legionaries
-// Features rounded dome, reinforced brow ridge, cheek guards, neck guard,
-// visor cross, breathing holes, brass decorations, and officer's plume/crest
-// Based on historical Roman legionary helmets
 class RomanHeavyHelmetRenderer : public IEquipmentRenderer {
 public:
   RomanHeavyHelmetRenderer() = default;

+ 6 - 18
render/equipment/helmets/roman_light_helmet.cpp

@@ -20,7 +20,7 @@ void RomanLightHelmetRenderer::render(const DrawContext &ctx,
                                       const HumanoidPalette &palette,
                                       const HumanoidAnimationContext &anim,
                                       ISubmitter &submitter) {
-  (void)anim; // Unused
+  (void)anim;
 
   const AttachmentFrame &head = frames.head;
   float const head_r = head.radius;
@@ -32,12 +32,10 @@ void RomanLightHelmetRenderer::render(const DrawContext &ctx,
     return HumanoidRendererBase::frameLocalPosition(head, normalized);
   };
 
-  // Roman galea (auxiliary helmet) - bronze/brass colored
   QVector3D const helmet_color =
       saturate_color(palette.metal * QVector3D(1.08F, 0.98F, 0.78F));
   QVector3D const helmet_accent = helmet_color * 1.12F;
 
-  // Main helmet bowl
   QVector3D const helmet_top = headPoint(QVector3D(0.0F, 1.28F, 0.0F));
   QVector3D const helmet_bot = headPoint(QVector3D(0.0F, 0.08F, 0.0F));
   float const helmet_r = head_r * 1.10F;
@@ -46,13 +44,11 @@ void RomanLightHelmetRenderer::render(const DrawContext &ctx,
                  cylinderBetween(ctx.model, helmet_bot, helmet_top, helmet_r),
                  helmet_color, nullptr, 1.0F);
 
-  // Conical top (characteristic Roman galea feature)
   QVector3D const apex_pos = headPoint(QVector3D(0.0F, 1.48F, 0.0F));
   submitter.mesh(getUnitCone(),
                  coneFromTo(ctx.model, helmet_top, apex_pos, helmet_r * 0.97F),
                  helmet_accent, nullptr, 1.0F);
 
-  // Decorative reinforcement rings
   auto ring = [&](float y_offset, float r_scale, float h,
                   const QVector3D &col) {
     QVector3D const center = headPoint(QVector3D(0.0F, y_offset, 0.0F));
@@ -67,32 +63,28 @@ void RomanLightHelmetRenderer::render(const DrawContext &ctx,
   ring(0.65F, 1.03F, 0.015F, helmet_color * 1.05F);
   ring(0.95F, 1.01F, 0.012F, helmet_color * 1.03F);
 
-  // Cheek guards (left and right)
   float const cheek_w = head_r * 0.48F;
   QVector3D const cheek_top = headPoint(QVector3D(0.0F, 0.22F, 0.0F));
   QVector3D const cheek_bot = headPoint(QVector3D(0.0F, -0.42F, 0.0F));
 
-  // Left cheek guard
   QVector3D const cheek_ltop =
       cheek_top + head.right * (-cheek_w / head_r) + head.forward * 0.38F;
   QVector3D const cheek_lbot = cheek_bot +
-                                head.right * (-cheek_w * 0.82F / head_r) +
-                                head.forward * 0.28F;
+                               head.right * (-cheek_w * 0.82F / head_r) +
+                               head.forward * 0.28F;
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, cheek_lbot, cheek_ltop, 0.028F),
                  helmet_color * 0.96F, nullptr, 1.0F);
 
-  // Right cheek guard
   QVector3D const cheek_rtop =
       cheek_top + head.right * (cheek_w / head_r) + head.forward * 0.38F;
-  QVector3D const cheek_rbot =
-      cheek_bot + head.right * (cheek_w * 0.82F / head_r) +
-      head.forward * 0.28F;
+  QVector3D const cheek_rbot = cheek_bot +
+                               head.right * (cheek_w * 0.82F / head_r) +
+                               head.forward * 0.28F;
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, cheek_rbot, cheek_rtop, 0.028F),
                  helmet_color * 0.96F, nullptr, 1.0F);
 
-  // Neck guard (back protection)
   QVector3D const neck_guard_top = headPoint(QVector3D(0.0F, 0.03F, -0.82F));
   QVector3D const neck_guard_bot = headPoint(QVector3D(0.0F, -0.32F, -0.88F));
   submitter.mesh(getUnitCylinder(),
@@ -100,22 +92,18 @@ void RomanLightHelmetRenderer::render(const DrawContext &ctx,
                                  helmet_r * 0.88F),
                  helmet_color * 0.93F, nullptr, 1.0F);
 
-  // Crest/plume for identification
   QVector3D const crest_base = apex_pos;
   QVector3D const crest_mid = crest_base + head.up * 0.09F;
   QVector3D const crest_top = crest_mid + head.up * 0.12F;
 
-  // Crest holder (metal)
   submitter.mesh(getUnitCylinder(),
                  cylinderBetween(ctx.model, crest_base, crest_mid, 0.018F),
                  helmet_accent, nullptr, 1.0F);
 
-  // Plume (red/crimson - traditional Roman color)
   submitter.mesh(getUnitCone(),
                  coneFromTo(ctx.model, crest_mid, crest_top, 0.042F),
                  QVector3D(0.88F, 0.18F, 0.18F), nullptr, 1.0F);
 
-  // Plume ornament (top ball)
   submitter.mesh(getUnitSphere(), sphereAt(ctx.model, crest_top, 0.020F),
                  helmet_accent, nullptr, 1.0F);
 }

+ 1 - 4
render/equipment/helmets/roman_light_helmet.h

@@ -1,14 +1,11 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 
 namespace Render::GL {
 
-// Roman light helmet - galea (auxiliary/archer helmet)
-// Features conical top, decorative rings, cheek guards, neck guard, and crest/plume
-// Based on historical Roman auxiliary helmets worn by archers and light infantry
 class RomanLightHelmetRenderer : public IEquipmentRenderer {
 public:
   RomanLightHelmetRenderer() = default;

+ 11 - 30
render/equipment/register_equipment.cpp

@@ -14,17 +14,14 @@ namespace Render::GL {
 void registerBuiltInEquipment() {
   auto &registry = EquipmentRegistry::instance();
 
-  // Register Carthaginian bow (composite recurve bow - Phoenician style)
-  // Carthaginians used composite bows influenced by Eastern Mediterranean designs
   BowRenderConfig carthage_config;
   carthage_config.bow_depth = 0.28F;
   carthage_config.bow_curve_factor = 1.2F;
   carthage_config.bow_height_scale = 0.95F;
   auto carthage_bow = std::make_shared<BowRenderer>(carthage_config);
-  registry.registerEquipment(EquipmentCategory::Weapon, "bow_carthage", carthage_bow);
+  registry.registerEquipment(EquipmentCategory::Weapon, "bow_carthage",
+                             carthage_bow);
 
-  // Register Roman bow (simple self bow with moderate curve)
-  // Romans primarily used simple wooden bows, less curved than composite bows
   BowRenderConfig roman_config;
   roman_config.bow_depth = 0.22F;
   roman_config.bow_curve_factor = 1.0F;
@@ -32,62 +29,46 @@ void registerBuiltInEquipment() {
   auto roman_bow = std::make_shared<BowRenderer>(roman_config);
   registry.registerEquipment(EquipmentCategory::Weapon, "bow_roman", roman_bow);
 
-  // Register Kingdom/European bow (longbow style - taller and straighter)
-  // European medieval longbows were characteristically tall and relatively straight
   BowRenderConfig kingdom_config;
   kingdom_config.bow_depth = 0.20F;
   kingdom_config.bow_curve_factor = 0.8F;
   kingdom_config.bow_height_scale = 1.15F;
   auto kingdom_bow = std::make_shared<BowRenderer>(kingdom_config);
-  registry.registerEquipment(EquipmentCategory::Weapon, "bow_kingdom", kingdom_bow);
+  registry.registerEquipment(EquipmentCategory::Weapon, "bow_kingdom",
+                             kingdom_bow);
 
-  // Register generic bow for backward compatibility
   auto bow = std::make_shared<BowRenderer>();
   registry.registerEquipment(EquipmentCategory::Weapon, "bow", bow);
 
-  // Register quiver renderer
   auto quiver = std::make_shared<QuiverRenderer>();
   registry.registerEquipment(EquipmentCategory::Weapon, "quiver", quiver);
 
-  // Register helmet renderers
-  // CARTHAGE HELMETS
-  // Montefortino helmet - Carthaginian/Punic style helmet with bronze bowl
-  // and distinctive top knob, used by heavy infantry (spearmen, swordsmen)
   auto montefortino_helmet = std::make_shared<MontefortinoHelmetRenderer>();
   registry.registerEquipment(EquipmentCategory::Helmet, "montefortino",
-                            montefortino_helmet);
+                             montefortino_helmet);
   registry.registerEquipment(EquipmentCategory::Helmet, "carthage_heavy",
-                            montefortino_helmet);
+                             montefortino_helmet);
 
-  // Headwrap - cloth head covering used by Carthaginian archers and light infantry
   auto headwrap = std::make_shared<HeadwrapRenderer>();
   registry.registerEquipment(EquipmentCategory::Helmet, "headwrap", headwrap);
   registry.registerEquipment(EquipmentCategory::Helmet, "carthage_light",
-                            headwrap);
+                             headwrap);
 
-  // ROMAN HELMETS
-  // Roman heavy helmet - Imperial Gallic style for legionaries with
-  // visor cross, breathing holes, and brass decorations
   auto roman_heavy = std::make_shared<RomanHeavyHelmetRenderer>();
   registry.registerEquipment(EquipmentCategory::Helmet, "roman_heavy",
-                            roman_heavy);
+                             roman_heavy);
 
-  // Roman light helmet - Simple cap helmet for archers and auxiliaries
   auto roman_light = std::make_shared<RomanLightHelmetRenderer>();
   registry.registerEquipment(EquipmentCategory::Helmet, "roman_light",
-                            roman_light);
+                             roman_light);
 
-  // KINGDOM HELMETS
-  // Kingdom heavy helmet - Great helm style for knights and heavy infantry
-  // with enclosed design and heraldic cross
   auto kingdom_heavy = std::make_shared<KingdomHeavyHelmetRenderer>();
   registry.registerEquipment(EquipmentCategory::Helmet, "kingdom_heavy",
-                            kingdom_heavy);
+                             kingdom_heavy);
 
-  // Kingdom light helmet - Kettle hat with wide brim for archers
   auto kingdom_light = std::make_shared<KingdomLightHelmetRenderer>();
   registry.registerEquipment(EquipmentCategory::Helmet, "kingdom_light",
-                            kingdom_light);
+                             kingdom_light);
 }
 
 } // namespace Render::GL

+ 46 - 51
render/equipment/weapons/bow_renderer.cpp

@@ -20,7 +20,8 @@ using Render::Geom::clampf;
 using Render::Geom::coneFromTo;
 using Render::Geom::cylinderBetween;
 
-BowRenderer::BowRenderer(BowRenderConfig config) : m_config(std::move(config)) {}
+BowRenderer::BowRenderer(BowRenderConfig config)
+    : m_config(std::move(config)) {}
 
 void BowRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
                          const HumanoidPalette &palette,
@@ -29,103 +30,97 @@ void BowRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
   const QVector3D up(0.0F, 1.0F, 0.0F);
   const QVector3D forward(0.0F, 0.0F, 1.0F);
 
-  // Get the left hand position (where bow is gripped)
   QVector3D const grip = frames.handL.origin;
 
-  // Bow ends in world coordinates
   float const bow_plane_z = 0.45F;
   QVector3D const top_end(m_config.bow_x, m_config.bow_top_y, bow_plane_z);
   QVector3D const bot_end(m_config.bow_x, m_config.bow_bot_y, bow_plane_z);
 
-  // Calculate nock position (where arrow attaches to string)
-  // The nock follows the right hand, clamped to bow bounds
   QVector3D const right_hand = frames.handR.origin;
   QVector3D const nock(
       m_config.bow_x,
-      clampf(right_hand.y(), m_config.bow_bot_y + 0.05F, m_config.bow_top_y - 0.05F),
+      clampf(right_hand.y(), m_config.bow_bot_y + 0.05F,
+             m_config.bow_top_y - 0.05F),
       clampf(right_hand.z(), bow_plane_z - 0.30F, bow_plane_z + 0.30F));
 
-  // Draw the bow arc using quadratic bezier
   constexpr int k_bowstring_segments = 22;
-  auto q_bezier = [](const QVector3D &a, const QVector3D &c,
-                     const QVector3D &b, float t) {
+  auto q_bezier = [](const QVector3D &a, const QVector3D &c, const QVector3D &b,
+                     float t) {
     float const u = 1.0F - t;
     return u * u * a + 2.0F * u * t * c + t * t * b;
   };
 
   float const bow_mid_y = (top_end.y() + bot_end.y()) * 0.5F;
   float const ctrl_y = bow_mid_y + (0.45F * m_config.bow_curve_factor);
-  QVector3D const ctrl(m_config.bow_x, ctrl_y, 
-                       bow_plane_z + m_config.bow_depth * 0.6F * m_config.bow_curve_factor);
+  QVector3D const ctrl(m_config.bow_x, ctrl_y,
+                       bow_plane_z + m_config.bow_depth * 0.6F *
+                                         m_config.bow_curve_factor);
 
-  // Draw bow limbs as segments
   QVector3D prev = bot_end;
   for (int i = 1; i <= k_bowstring_segments; ++i) {
     float const t = float(i) / float(k_bowstring_segments);
     QVector3D const cur = q_bezier(bot_end, ctrl, top_end, t);
-    submitter.mesh(getUnitCylinder(),
-                   cylinderBetween(ctx.model, prev, cur, m_config.bow_rod_radius),
-                   palette.wood, nullptr, 1.0F);
+    submitter.mesh(
+        getUnitCylinder(),
+        cylinderBetween(ctx.model, prev, cur, m_config.bow_rod_radius),
+        palette.wood, nullptr, 1.0F);
     prev = cur;
   }
 
-  // Draw the grip (thicker section at hand)
   submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, grip - up * 0.05F, grip + up * 0.05F,
-                                m_config.bow_rod_radius * 1.45F),
+                 cylinderBetween(ctx.model, grip - up * 0.05F,
+                                 grip + up * 0.05F,
+                                 m_config.bow_rod_radius * 1.45F),
                  palette.wood, nullptr, 1.0F);
 
-  // Draw bowstring
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, top_end, nock, m_config.string_radius),
-                 m_config.string_color, nullptr, 1.0F);
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, nock, bot_end, m_config.string_radius),
-                 m_config.string_color, nullptr, 1.0F);
-
-  // Draw string from right hand to nock (when drawn)
-  bool const is_bow_attacking = anim.inputs.is_attacking && !anim.inputs.isMelee;
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, top_end, nock, m_config.string_radius),
+      m_config.string_color, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, nock, bot_end, m_config.string_radius),
+      m_config.string_color, nullptr, 1.0F);
+
+  bool const is_bow_attacking =
+      anim.inputs.is_attacking && !anim.inputs.isMelee;
   if (is_bow_attacking) {
-    submitter.mesh(getUnitCylinder(),
-                   cylinderBetween(ctx.model, frames.handR.origin, nock, 0.0045F),
-                   m_config.string_color * 0.9F, nullptr, 1.0F);
+    submitter.mesh(
+        getUnitCylinder(),
+        cylinderBetween(ctx.model, frames.handR.origin, nock, 0.0045F),
+        m_config.string_color * 0.9F, nullptr, 1.0F);
   }
 
-  // Draw arrow (when not in flight)
   float attack_phase = 0.0F;
   if (is_bow_attacking) {
-    attack_phase = std::fmod(anim.inputs.time * ARCHER_INV_ATTACK_CYCLE_TIME, 1.0F);
+    attack_phase =
+        std::fmod(anim.inputs.time * ARCHER_INV_ATTACK_CYCLE_TIME, 1.0F);
   }
 
-  bool const show_arrow = !is_bow_attacking || 
-                          (is_bow_attacking && attack_phase >= 0.0F && attack_phase < 0.52F);
+  bool const show_arrow =
+      !is_bow_attacking ||
+      (is_bow_attacking && attack_phase >= 0.0F && attack_phase < 0.52F);
 
   if (show_arrow) {
     QVector3D const tail = nock - forward * 0.06F;
     QVector3D const tip = tail + forward * 0.90F;
-    
-    // Arrow shaft
-    submitter.mesh(getUnitCylinder(), 
-                   cylinderBetween(ctx.model, tail, tip, 0.018F),
-                   palette.wood, nullptr, 1.0F);
-    
-    // Arrow head
+
+    submitter.mesh(getUnitCylinder(),
+                   cylinderBetween(ctx.model, tail, tip, 0.018F), palette.wood,
+                   nullptr, 1.0F);
+
     QVector3D const head_base = tip - forward * 0.10F;
-    submitter.mesh(getUnitCone(), 
-                   coneFromTo(ctx.model, head_base, tip, 0.05F),
+    submitter.mesh(getUnitCone(), coneFromTo(ctx.model, head_base, tip, 0.05F),
                    m_config.metal_color, nullptr, 1.0F);
-    
-    // Fletching
+
     QVector3D const f1b = tail - forward * 0.02F;
     QVector3D const f1a = f1b - forward * 0.06F;
     QVector3D const f2b = tail + forward * 0.02F;
     QVector3D const f2a = f2b + forward * 0.06F;
-    
-    submitter.mesh(getUnitCone(), 
-                   coneFromTo(ctx.model, f1b, f1a, 0.04F),
+
+    submitter.mesh(getUnitCone(), coneFromTo(ctx.model, f1b, f1a, 0.04F),
                    m_config.fletching_color, nullptr, 1.0F);
-    submitter.mesh(getUnitCone(), 
-                   coneFromTo(ctx.model, f2a, f2b, 0.04F),
+    submitter.mesh(getUnitCone(), coneFromTo(ctx.model, f2a, f2b, 0.04F),
                    m_config.fletching_color, nullptr, 1.0F);
   }
 }

+ 6 - 6
render/equipment/weapons/bow_renderer.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 #include <QVector3D>
 
 namespace Render::GL {
@@ -13,12 +13,12 @@ struct BowRenderConfig {
   QVector3D fletching_color{0.60F, 0.20F, 0.20F};
   float bow_rod_radius = 0.035F;
   float string_radius = 0.008F;
-  float bow_depth = 0.25F;      // Curve depth (composite bows have more)
+  float bow_depth = 0.25F;
   float bow_x = 0.0F;
-  float bow_top_y = 0.0F;       // Set based on HumanProportions
-  float bow_bot_y = 0.0F;       // Set based on HumanProportions
-  float bow_height_scale = 1.0F; // Height multiplier (longbows are taller)
-  float bow_curve_factor = 1.0F; // Curve intensity (composite bows curve more)
+  float bow_top_y = 0.0F;
+  float bow_bot_y = 0.0F;
+  float bow_height_scale = 1.0F;
+  float bow_curve_factor = 1.0F;
 };
 
 class BowRenderer : public IEquipmentRenderer {

+ 21 - 25
render/equipment/weapons/quiver_renderer.cpp

@@ -18,54 +18,50 @@ using Render::Geom::coneFromTo;
 using Render::Geom::cylinderBetween;
 using Render::GL::HashXorShift::k_golden_ratio;
 
-QuiverRenderer::QuiverRenderer(QuiverRenderConfig config) 
+QuiverRenderer::QuiverRenderer(QuiverRenderConfig config)
     : m_config(std::move(config)) {}
 
 void QuiverRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
-                           const HumanoidPalette &palette,
-                           const HumanoidAnimationContext & /*anim*/,
-                           ISubmitter &submitter) {
-  // Use the shoulder positions to compute quiver location
-  // This matches the original implementation which used:
-  // spine_mid = (pose.shoulderL + pose.shoulderR) * 0.5F
-  QVector3D const spine_mid = (frames.shoulderL.origin + frames.shoulderR.origin) * 0.5F;
+                            const HumanoidPalette &palette,
+                            const HumanoidAnimationContext &,
+                            ISubmitter &submitter) {
+
+  QVector3D const spine_mid =
+      (frames.shoulderL.origin + frames.shoulderR.origin) * 0.5F;
   QVector3D const quiver_offset(-0.08F, 0.10F, -0.25F);
   QVector3D const q_top = spine_mid + quiver_offset;
   QVector3D const q_base = q_top + QVector3D(-0.02F, -0.30F, 0.03F);
 
-  // Draw the quiver cylinder
-  submitter.mesh(getUnitCylinder(),
-                 cylinderBetween(ctx.model, q_base, q_top, m_config.quiver_radius),
-                 palette.leather, nullptr, 1.0F);
+  submitter.mesh(
+      getUnitCylinder(),
+      cylinderBetween(ctx.model, q_base, q_top, m_config.quiver_radius),
+      palette.leather, nullptr, 1.0F);
 
-  // Generate a seed for arrow jitter based on entity pointer
   uint32_t seed = 0U;
   if (ctx.entity != nullptr) {
     seed = uint32_t(reinterpret_cast<uintptr_t>(ctx.entity) & 0xFFFFFFFFU);
   }
 
-  // Draw arrows sticking out of the quiver
   float const j = (hash_01(seed) - 0.5F) * 0.04F;
   float const k = (hash_01(seed ^ k_golden_ratio) - 0.5F) * 0.04F;
 
-  // First arrow
   QVector3D const a1 = q_top + QVector3D(0.00F + j, 0.08F, 0.00F + k);
-  submitter.mesh(getUnitCylinder(), 
-                 cylinderBetween(ctx.model, q_top, a1, 0.010F),
-                 palette.wood, nullptr, 1.0F);
+  submitter.mesh(getUnitCylinder(),
+                 cylinderBetween(ctx.model, q_top, a1, 0.010F), palette.wood,
+                 nullptr, 1.0F);
   submitter.mesh(getUnitCone(),
                  coneFromTo(ctx.model, a1, a1 + QVector3D(0, 0.05F, 0), 0.025F),
                  m_config.fletching_color, nullptr, 1.0F);
 
-  // Second arrow (if configured)
   if (m_config.num_arrows >= 2) {
     QVector3D const a2 = q_top + QVector3D(0.02F - j, 0.07F, 0.02F - k);
-    submitter.mesh(getUnitCylinder(), 
-                   cylinderBetween(ctx.model, q_top, a2, 0.010F),
-                   palette.wood, nullptr, 1.0F);
-    submitter.mesh(getUnitCone(),
-                   coneFromTo(ctx.model, a2, a2 + QVector3D(0, 0.05F, 0), 0.025F),
-                   m_config.fletching_color, nullptr, 1.0F);
+    submitter.mesh(getUnitCylinder(),
+                   cylinderBetween(ctx.model, q_top, a2, 0.010F), palette.wood,
+                   nullptr, 1.0F);
+    submitter.mesh(
+        getUnitCone(),
+        coneFromTo(ctx.model, a2, a2 + QVector3D(0, 0.05F, 0), 0.025F),
+        m_config.fletching_color, nullptr, 1.0F);
   }
 }
 

+ 1 - 1
render/equipment/weapons/quiver_renderer.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include "../i_equipment_renderer.h"
 #include "../../humanoid/rig.h"
 #include "../../palette.h"
+#include "../i_equipment_renderer.h"
 #include <QVector3D>
 
 namespace Render::GL {

+ 38 - 69
render/humanoid/pose_controller.cpp

@@ -11,43 +11,31 @@ HumanoidPoseController::HumanoidPoseController(
     HumanoidPose &pose, const HumanoidAnimationContext &anim_ctx)
     : m_pose(pose), m_anim_ctx(anim_ctx) {}
 
-// ---- Basic Stance Methods ----
-
-void HumanoidPoseController::standIdle() {
-  // Set to neutral standing pose - this is a no-op as the base locomotion
-  // pose should already be in a standing idle state.
-  // This method is provided for explicit API clarity.
-}
+void HumanoidPoseController::standIdle() {}
 
 void HumanoidPoseController::kneel(float depth) {
   using HP = HumanProportions;
-  
-  // Clamp depth to valid range
+
   depth = std::clamp(depth, 0.0F, 1.0F);
-  
-  // Lower pelvis based on kneel depth
-  float const kneel_offset = depth * 0.40F; // Max kneel depth
+
+  float const kneel_offset = depth * 0.40F;
   float const pelvis_y = HP::WAIST_Y - kneel_offset;
   m_pose.pelvisPos.setY(pelvis_y);
-  
-  // Adjust stance width when kneeling
+
   float const stance_narrow = 0.11F;
-  
-  // Left leg: knee touches ground when fully kneeling
+
   float const left_knee_y = HP::GROUND_Y + 0.07F * depth;
   float const left_knee_z = -0.06F * depth;
   m_pose.knee_l = QVector3D(-stance_narrow, left_knee_y, left_knee_z);
   m_pose.footL = QVector3D(-stance_narrow - 0.025F, HP::GROUND_Y,
                            left_knee_z - HP::LOWER_LEG_LEN * 0.93F * depth);
-  
-  // Right leg: stays more upright
+
   float const right_knee_y = pelvis_y - 0.12F;
   float const right_foot_z = 0.28F * depth;
   m_pose.knee_r = QVector3D(stance_narrow, right_knee_y, right_foot_z - 0.05F);
-  m_pose.foot_r = QVector3D(stance_narrow, HP::GROUND_Y + m_pose.footYOffset,
-                            right_foot_z);
-  
-  // Lower upper body
+  m_pose.foot_r =
+      QVector3D(stance_narrow, HP::GROUND_Y + m_pose.footYOffset, right_foot_z);
+
   float const upper_body_drop = kneel_offset;
   m_pose.shoulderL.setY(m_pose.shoulderL.y() - upper_body_drop);
   m_pose.shoulderR.setY(m_pose.shoulderR.y() - upper_body_drop);
@@ -56,75 +44,63 @@ void HumanoidPoseController::kneel(float depth) {
 }
 
 void HumanoidPoseController::lean(const QVector3D &direction, float amount) {
-  // Clamp amount to valid range
+
   amount = std::clamp(amount, 0.0F, 1.0F);
-  
-  // Normalize direction
+
   QVector3D dir = direction;
   if (dir.lengthSquared() > 1e-6F) {
     dir.normalize();
   } else {
-    dir = QVector3D(0.0F, 0.0F, 1.0F); // Default forward
+    dir = QVector3D(0.0F, 0.0F, 1.0F);
   }
-  
-  // Apply lean to upper body
+
   float const lean_magnitude = 0.12F * amount;
   QVector3D const lean_offset = dir * lean_magnitude;
-  
+
   m_pose.shoulderL += lean_offset;
   m_pose.shoulderR += lean_offset;
   m_pose.neck_base += lean_offset * 0.85F;
   m_pose.headPos += lean_offset * 0.75F;
 }
 
-// ---- Hand Positioning ----
-
 void HumanoidPoseController::placeHandAt(bool is_left,
                                          const QVector3D &target_position) {
-  // Set hand position
+
   getHand(is_left) = target_position;
-  
-  // Solve elbow position using IK
+
   const QVector3D &shoulder = getShoulder(is_left);
   const QVector3D outward_dir = computeOutwardDir(is_left);
-  
-  // Standard IK parameters for natural arm bend
+
   float const along_frac = is_left ? 0.45F : 0.48F;
   float const lateral_offset = is_left ? 0.15F : 0.12F;
   float const y_bias = is_left ? -0.08F : 0.02F;
   float const outward_sign = 1.0F;
-  
-  getElbow(is_left) = solveElbowIK(is_left, shoulder, target_position,
-                                   outward_dir, along_frac, lateral_offset,
-                                   y_bias, outward_sign);
+
+  getElbow(is_left) =
+      solveElbowIK(is_left, shoulder, target_position, outward_dir, along_frac,
+                   lateral_offset, y_bias, outward_sign);
 }
 
-// ---- Low-level IK Utilities ----
+auto HumanoidPoseController::solveElbowIK(
+    bool, const QVector3D &shoulder, const QVector3D &hand,
+    const QVector3D &outward_dir, float along_frac, float lateral_offset,
+    float y_bias, float outward_sign) const -> QVector3D {
 
-auto HumanoidPoseController::solveElbowIK(bool /*is_left*/,
-                                          const QVector3D &shoulder,
-                                          const QVector3D &hand,
-                                          const QVector3D &outward_dir,
-                                          float along_frac, float lateral_offset,
-                                          float y_bias,
-                                          float outward_sign) const
-    -> QVector3D {
-  // Use the existing elbowBendTorso function from humanoid_math
   return elbowBendTorso(shoulder, hand, outward_dir, along_frac, lateral_offset,
                         y_bias, outward_sign);
 }
 
-auto HumanoidPoseController::solveKneeIK(bool is_left, const QVector3D &hip,
-                                         const QVector3D &foot,
-                                         float height_scale) const -> QVector3D {
+auto HumanoidPoseController::solveKneeIK(
+    bool is_left, const QVector3D &hip, const QVector3D &foot,
+    float height_scale) const -> QVector3D {
   using HP = HumanProportions;
-  
+
   QVector3D hip_to_foot = foot - hip;
   float const distance = hip_to_foot.length();
   if (distance < 1e-5F) {
     return hip;
   }
-  
+
   float const upper_len = HP::UPPER_LEG_LEN * height_scale;
   float const lower_len = HP::LOWER_LEG_LEN * height_scale;
   float const reach = upper_len + lower_len;
@@ -132,23 +108,20 @@ auto HumanoidPoseController::solveKneeIK(bool is_left, const QVector3D &hip,
       std::max(std::abs(upper_len - lower_len) + 1e-4F, 1e-3F);
   float const max_reach = std::max(reach - 1e-4F, min_reach + 1e-4F);
   float const clamped_dist = std::clamp(distance, min_reach, max_reach);
-  
+
   QVector3D const dir = hip_to_foot / distance;
-  
-  // Law of cosines to find knee angle
+
   float cos_theta = (upper_len * upper_len + clamped_dist * clamped_dist -
                      lower_len * lower_len) /
                     (2.0F * upper_len * clamped_dist);
   cos_theta = std::clamp(cos_theta, -1.0F, 1.0F);
   float const sin_theta =
       std::sqrt(std::max(0.0F, 1.0F - cos_theta * cos_theta));
-  
-  // Preferred knee bend direction (forward and slightly outward)
+
   QVector3D bend_pref =
       is_left ? QVector3D(-0.24F, 0.0F, 0.95F) : QVector3D(0.24F, 0.0F, 0.95F);
   bend_pref.normalize();
-  
-  // Compute bend axis perpendicular to leg direction
+
   QVector3D bend_axis = bend_pref - dir * QVector3D::dotProduct(dir, bend_pref);
   if (bend_axis.lengthSquared() < 1e-6F) {
     bend_axis = QVector3D::crossProduct(dir, QVector3D(0.0F, 1.0F, 0.0F));
@@ -157,24 +130,20 @@ auto HumanoidPoseController::solveKneeIK(bool is_left, const QVector3D &hip,
     }
   }
   bend_axis.normalize();
-  
-  // Compute knee position
+
   QVector3D const knee =
       hip + dir * (cos_theta * upper_len) + bend_axis * (sin_theta * upper_len);
-  
-  // Prevent knee from going below ground
+
   float const knee_floor = HP::GROUND_Y + m_pose.footYOffset * 0.5F;
   if (knee.y() < knee_floor) {
     QVector3D adjusted = knee;
     adjusted.setY(knee_floor);
     return adjusted;
   }
-  
+
   return knee;
 }
 
-// ---- Private Helper Methods ----
-
 auto HumanoidPoseController::getShoulder(bool is_left) const
     -> const QVector3D & {
   return is_left ? m_pose.shoulderL : m_pose.shoulderR;

+ 5 - 72
render/humanoid/pose_controller.h

@@ -1,92 +1,30 @@
 #pragma once
 
-#include "rig.h"
 #include "humanoid_specs.h"
+#include "rig.h"
 #include <QVector3D>
 #include <cstdint>
 
 namespace Render::GL {
 
-/**
- * High-level pose controller API that encapsulates low-level joint manipulation logic.
- * Unit renderers should call methods like kneel(), aimBow(), or meleeStrike() instead
- * of directly setting pose coordinates.
- */
 class HumanoidPoseController {
 public:
-  /**
-   * Construct a pose controller operating on the given pose and animation context.
-   * 
-   * @param pose Reference to the HumanoidPose to manipulate
-   * @param anim_ctx Animation context providing motion state and timing information
-   */
   HumanoidPoseController(HumanoidPose &pose,
                          const HumanoidAnimationContext &anim_ctx);
 
-  // ---- Basic Stance Methods ----
-
-  /**
-   * Set the humanoid to a standing idle pose.
-   * This is the default neutral stance.
-   */
   void standIdle();
 
-  /**
-   * Make the humanoid kneel down.
-   * 
-   * @param depth Kneel depth factor (0.0 = standing, 1.0 = full kneel)
-   */
   void kneel(float depth);
 
-  /**
-   * Lean the body in a specific direction.
-   * 
-   * @param direction Direction vector to lean towards (normalized)
-   * @param amount Lean amount (0.0 = upright, 1.0 = maximum lean)
-   */
   void lean(const QVector3D &direction, float amount);
 
-  // ---- Hand Positioning ----
-
-  /**
-   * Position a hand at a target position, computing elbow via IK.
-   * 
-   * @param is_left True for left hand, false for right hand
-   * @param target_position World position to place the hand at
-   */
   void placeHandAt(bool is_left, const QVector3D &target_position);
 
-  // ---- Low-level IK Utilities ----
-
-  /**
-   * Solve elbow position using inverse kinematics for torso-relative arms.
-   * This is the low-level IK logic extracted from the base renderer.
-   * 
-   * @param is_left True for left arm, false for right arm
-   * @param shoulder Shoulder position
-   * @param hand Hand position
-   * @param outward_dir Outward direction vector for elbow bend
-   * @param along_frac Fraction along the arm (0.0-1.0) to place elbow
-   * @param lateral_offset Lateral offset for elbow bend
-   * @param y_bias Vertical bias for elbow position
-   * @param outward_sign Sign multiplier for outward direction (+1.0 or -1.0)
-   * @return Computed elbow position
-   */
   auto solveElbowIK(bool is_left, const QVector3D &shoulder,
                     const QVector3D &hand, const QVector3D &outward_dir,
                     float along_frac, float lateral_offset, float y_bias,
                     float outward_sign) const -> QVector3D;
 
-  /**
-   * Solve knee position using inverse kinematics for leg.
-   * This is the low-level IK logic extracted from the base renderer.
-   * 
-   * @param is_left True for left leg, false for right leg
-   * @param hip Hip position
-   * @param foot Foot position
-   * @param height_scale Height scaling factor for proportions
-   * @return Computed knee position
-   */
   auto solveKneeIK(bool is_left, const QVector3D &hip, const QVector3D &foot,
                    float height_scale) const -> QVector3D;
 
@@ -94,20 +32,15 @@ private:
   HumanoidPose &m_pose;
   const HumanoidAnimationContext &m_anim_ctx;
 
-  // Helper to get shoulder position for the specified side
   auto getShoulder(bool is_left) const -> const QVector3D &;
-  
-  // Helper to get hand position reference for the specified side
+
   auto getHand(bool is_left) -> QVector3D &;
   auto getHand(bool is_left) const -> const QVector3D &;
-  
-  // Helper to get elbow position reference for the specified side
+
   auto getElbow(bool is_left) -> QVector3D &;
-  
-  // Helper to compute right axis from shoulders
+
   auto computeRightAxis() const -> QVector3D;
-  
-  // Helper to compute outward direction for arm
+
   auto computeOutwardDir(bool is_left) const -> QVector3D;
 };
 

+ 10 - 14
render/humanoid/rig.cpp

@@ -66,7 +66,6 @@ auto HumanoidRendererBase::makeFrameLocalTransform(
   return parent * local;
 }
 
-// Legacy backward-compatible wrappers
 auto HumanoidRendererBase::headLocalPosition(
     const HeadFrame &frame, const QVector3D &local) -> QVector3D {
   return frameLocalPosition(frame, local);
@@ -501,46 +500,44 @@ void HumanoidRendererBase::drawCommonBody(const DrawContext &ctx,
   pose.headFrame.forward = head_forward;
   pose.headFrame.radius = head_r;
 
-  // Populate all body frames
   pose.bodyFrames.head = pose.headFrame;
 
-  // Torso frame (centered at shoulder level)
   pose.bodyFrames.torso.origin = QVector3D(0.0F, y_shoulder, 0.0F);
   pose.bodyFrames.torso.right = right_axis;
   pose.bodyFrames.torso.up = up_axis;
   pose.bodyFrames.torso.forward = forward_axis;
   pose.bodyFrames.torso.radius = torso_r;
 
-  // Back frame (behind torso)
-  pose.bodyFrames.back.origin = QVector3D(0.0F, y_shoulder, 0.0F) - forward_axis * (torso_r * 0.65F);
+  pose.bodyFrames.back.origin =
+      QVector3D(0.0F, y_shoulder, 0.0F) - forward_axis * (torso_r * 0.65F);
   pose.bodyFrames.back.right = right_axis;
   pose.bodyFrames.back.up = up_axis;
-  pose.bodyFrames.back.forward = -forward_axis;  // Facing backward
+  pose.bodyFrames.back.forward = -forward_axis;
   pose.bodyFrames.back.radius = torso_r * 0.8F;
 
-  // Waist frame
   pose.bodyFrames.waist.origin = pose.pelvisPos;
   pose.bodyFrames.waist.right = right_axis;
   pose.bodyFrames.waist.up = up_axis;
   pose.bodyFrames.waist.forward = forward_axis;
   pose.bodyFrames.waist.radius = torso_r * 0.85F;
 
-  // Shoulder frames
   QVector3D shoulder_up = (pose.shoulderL - pose.pelvisPos).normalized();
-  QVector3D shoulder_forward_l = QVector3D::crossProduct(-right_axis, shoulder_up);
+  QVector3D shoulder_forward_l =
+      QVector3D::crossProduct(-right_axis, shoulder_up);
   if (shoulder_forward_l.lengthSquared() < 1e-8F) {
     shoulder_forward_l = forward_axis;
   } else {
     shoulder_forward_l.normalize();
   }
-  
+
   pose.bodyFrames.shoulderL.origin = pose.shoulderL;
   pose.bodyFrames.shoulderL.right = -right_axis;
   pose.bodyFrames.shoulderL.up = shoulder_up;
   pose.bodyFrames.shoulderL.forward = shoulder_forward_l;
   pose.bodyFrames.shoulderL.radius = upper_arm_r;
 
-  QVector3D shoulder_forward_r = QVector3D::crossProduct(right_axis, shoulder_up);
+  QVector3D shoulder_forward_r =
+      QVector3D::crossProduct(right_axis, shoulder_up);
   if (shoulder_forward_r.lengthSquared() < 1e-8F) {
     shoulder_forward_r = forward_axis;
   } else {
@@ -553,7 +550,6 @@ void HumanoidRendererBase::drawCommonBody(const DrawContext &ctx,
   pose.bodyFrames.shoulderR.forward = shoulder_forward_r;
   pose.bodyFrames.shoulderR.radius = upper_arm_r;
 
-  // Hand frames
   QVector3D hand_up_l = (pose.handL - pose.elbowL);
   if (hand_up_l.lengthSquared() > 1e-8F) {
     hand_up_l.normalize();
@@ -592,7 +588,6 @@ void HumanoidRendererBase::drawCommonBody(const DrawContext &ctx,
   pose.bodyFrames.handR.forward = hand_forward_r;
   pose.bodyFrames.handR.radius = hand_r;
 
-  // Foot frames
   QVector3D foot_up_l = up_axis;
   QVector3D foot_forward_l = forward_axis - right_axis * 0.12F;
   if (foot_forward_l.lengthSquared() > 1e-8F) {
@@ -624,7 +619,8 @@ void HumanoidRendererBase::drawCommonBody(const DrawContext &ctx,
   auto eyePosition = [&](float lateral) {
     QVector3D const local(lateral, 0.12F, 0.92F);
     QVector3D world = frameLocalPosition(pose.bodyFrames.head, local);
-    world += pose.bodyFrames.head.forward * (pose.bodyFrames.head.radius * 0.02F);
+    world +=
+        pose.bodyFrames.head.forward * (pose.bodyFrames.head.radius * 0.02F);
     return world;
   };
   QVector3D const left_eye_world = eyePosition(-0.32F);

+ 0 - 5
render/humanoid/rig.h

@@ -40,7 +40,6 @@ struct AttachmentFrame {
   float radius{0.0F};
 };
 
-// Legacy alias for backward compatibility
 using HeadFrame = AttachmentFrame;
 
 struct BodyFrames {
@@ -61,10 +60,8 @@ struct HumanoidPose {
   float headR{};
   QVector3D neck_base;
 
-  // Legacy field for backward compatibility - points to bodyFrames.head
   HeadFrame headFrame{};
 
-  // Complete body attachment frame system
   BodyFrames bodyFrames{};
 
   QVector3D shoulderL, shoulderR;
@@ -245,7 +242,6 @@ public:
 
   void render(const DrawContext &ctx, ISubmitter &out) const;
 
-  // Frame coordinate transformation helpers (public for testing and external use)
   static auto frameLocalPosition(const AttachmentFrame &frame,
                                  const QVector3D &local) -> QVector3D;
 
@@ -254,7 +250,6 @@ public:
                                       const QVector3D &local_offset,
                                       float uniform_scale) -> QMatrix4x4;
 
-  // Legacy helpers for backward compatibility
   static auto headLocalPosition(const HeadFrame &frame,
                                 const QVector3D &local) -> QVector3D;
 

+ 18 - 17
tests/render/body_frames_test.cpp

@@ -1,9 +1,9 @@
-#include "render/humanoid/rig.h"
 #include "render/humanoid/humanoid_specs.h"
-#include <QVector3D>
+#include "render/humanoid/rig.h"
 #include <QMatrix4x4>
-#include <gtest/gtest.h>
+#include <QVector3D>
 #include <cmath>
+#include <gtest/gtest.h>
 
 using namespace Render::GL;
 
@@ -27,7 +27,8 @@ protected:
 
   HumanoidPose pose;
 
-  bool approxEqual(const QVector3D &a, const QVector3D &b, float epsilon = 0.01F) {
+  bool approxEqual(const QVector3D &a, const QVector3D &b,
+                   float epsilon = 0.01F) {
     return std::abs(a.x() - b.x()) < epsilon &&
            std::abs(a.y() - b.y()) < epsilon &&
            std::abs(a.z() - b.z()) < epsilon;
@@ -51,10 +52,10 @@ TEST_F(BodyFramesTest, HeadFrameIsAliasForAttachmentFrame) {
   // Verify that HeadFrame is an alias and can be used interchangeably
   HeadFrame headFrame;
   AttachmentFrame attachFrame;
-  
+
   headFrame.origin = QVector3D(1.0F, 2.0F, 3.0F);
   headFrame.radius = 0.5F;
-  
+
   attachFrame = headFrame;
   EXPECT_EQ(attachFrame.origin, QVector3D(1.0F, 2.0F, 3.0F));
   EXPECT_EQ(attachFrame.radius, 0.5F);
@@ -62,7 +63,7 @@ TEST_F(BodyFramesTest, HeadFrameIsAliasForAttachmentFrame) {
 
 TEST_F(BodyFramesTest, BodyFramesHasAllRequiredFrames) {
   BodyFrames frames;
-  
+
   // Verify all frames exist and are initialized to default
   EXPECT_EQ(frames.head.origin, QVector3D(0.0F, 0.0F, 0.0F));
   EXPECT_EQ(frames.torso.origin, QVector3D(0.0F, 0.0F, 0.0F));
@@ -85,9 +86,9 @@ TEST_F(BodyFramesTest, FrameLocalPositionComputesCorrectly) {
   frame.radius = 0.5F;
 
   // Test frame-local position computation
-  QVector3D local(1.0F, 0.0F, 0.0F);  // Right
+  QVector3D local(1.0F, 0.0F, 0.0F); // Right
   QVector3D world = HumanoidRendererBase::frameLocalPosition(frame, local);
-  
+
   // Expected: origin + right * (1.0 * radius)
   QVector3D expected = QVector3D(1.5F, 2.0F, 3.0F);
   EXPECT_TRUE(approxEqual(world, expected));
@@ -104,7 +105,7 @@ TEST_F(BodyFramesTest, FrameLocalPositionWithMultipleAxes) {
   // Test diagonal position
   QVector3D local(1.0F, 1.0F, 1.0F);
   QVector3D world = HumanoidRendererBase::frameLocalPosition(frame, local);
-  
+
   // Expected: origin + right*1 + up*1 + forward*1
   QVector3D expected = QVector3D(1.0F, 1.0F, 1.0F);
   EXPECT_TRUE(approxEqual(world, expected));
@@ -118,7 +119,7 @@ TEST_F(BodyFramesTest, MakeFrameLocalTransformCreatesValidMatrix) {
   frame.forward = QVector3D(0.0F, 0.0F, 1.0F);
   frame.radius = 0.5F;
 
-  QMatrix4x4 parent;  // Identity matrix
+  QMatrix4x4 parent; // Identity matrix
   QVector3D localOffset(0.0F, 0.0F, 0.0F);
   float uniformScale = 1.0F;
 
@@ -148,26 +149,26 @@ TEST_F(BodyFramesTest, LegacyHeadFunctionsStillWork) {
   QMatrix4x4 parent;
   QVector3D localOffset(0.0F, 0.0F, 0.0F);
   float uniformScale = 1.0F;
-  
+
   QMatrix4x4 result = HumanoidRendererBase::makeHeadLocalTransform(
       parent, headFrame, localOffset, uniformScale);
-  
+
   QVector3D translation = result.map(QVector3D(0.0F, 0.0F, 0.0F));
   EXPECT_TRUE(approxEqual(translation, headFrame.origin));
 }
 
 TEST_F(BodyFramesTest, PoseHasBothHeadFrameAndBodyFrames) {
   // Verify that the pose has both the legacy headFrame and new bodyFrames
-  EXPECT_TRUE(true);  // Just verify it compiles
-  
+  EXPECT_TRUE(true); // Just verify it compiles
+
   // Set headFrame
   pose.headFrame.origin = QVector3D(0.0F, 1.7F, 0.0F);
   pose.headFrame.radius = 0.1F;
-  
+
   // Set bodyFrames.head
   pose.bodyFrames.head.origin = QVector3D(0.0F, 1.7F, 0.0F);
   pose.bodyFrames.head.radius = 0.1F;
-  
+
   // Verify both can be accessed
   EXPECT_EQ(pose.headFrame.origin, QVector3D(0.0F, 1.7F, 0.0F));
   EXPECT_EQ(pose.bodyFrames.head.origin, QVector3D(0.0F, 1.7F, 0.0F));

+ 7 - 6
tests/render/helmet_renderers_test.cpp

@@ -26,17 +26,18 @@ public:
   }
 
   void selectionRing(const QMatrix4x4 & /*model*/, float /*alphaInner*/,
-                     float /*alphaOuter*/, const QVector3D & /*color*/) override {
+                     float /*alphaOuter*/,
+                     const QVector3D & /*color*/) override {
     // Not used in helmet rendering
   }
 
   void grid(const QMatrix4x4 & /*model*/, const QVector3D & /*color*/,
-            float /*cellSize*/, float /*thickness*/, float /*extent*/) override {
+            float /*cellSize*/, float /*thickness*/,
+            float /*extent*/) override {
     // Not used in helmet rendering
   }
 
-  void selectionSmoke(const QMatrix4x4 & /*model*/,
-                      const QVector3D & /*color*/,
+  void selectionSmoke(const QMatrix4x4 & /*model*/, const QVector3D & /*color*/,
                       float /*baseAlpha*/) override {
     // Not used in helmet rendering
   }
@@ -84,7 +85,7 @@ protected:
   void SetUp() override {
     // Ensure built-in equipment is registered
     registerBuiltInEquipment();
-    
+
     ctx = createTestContext();
     frames = createTestFrames();
     palette = createTestPalette();
@@ -176,7 +177,7 @@ TEST_F(HelmetRenderersTest, HeadwrapFromRegistryRenders) {
 TEST_F(HelmetRenderersTest, HelmetsUseHeadFrameCoordinates) {
   // Test that helmets use head frame's coordinate system
   frames.head.origin = QVector3D(1.0F, 2.0F, 3.0F);
-  frames.head.right = QVector3D(0.0F, 1.0F, 0.0F);  // Rotated frame
+  frames.head.right = QVector3D(0.0F, 1.0F, 0.0F); // Rotated frame
   frames.head.up = QVector3D(-1.0F, 0.0F, 0.0F);
   frames.head.forward = QVector3D(0.0F, 0.0F, 1.0F);
   frames.head.radius = 0.12F;

+ 61 - 52
tests/render/pose_controller_compatibility_test.cpp

@@ -1,10 +1,10 @@
-#include "render/humanoid/pose_controller.h"
 #include "render/humanoid/humanoid_math.h"
 #include "render/humanoid/humanoid_specs.h"
+#include "render/humanoid/pose_controller.h"
 #include "render/humanoid/rig.h"
 #include <QVector3D>
-#include <gtest/gtest.h>
 #include <cmath>
+#include <gtest/gtest.h>
 
 using namespace Render::GL;
 
@@ -46,7 +46,7 @@ protected:
 
 TEST_F(PoseControllerCompatibilityTest, ElbowIKMatchesLegacyFunction) {
   // Test that controller's solveElbowIK produces same result as elbowBendTorso
-  
+
   QVector3D const shoulder(0.21F, 1.45F, 0.0F);
   QVector3D const hand(0.35F, 1.15F, 0.75F);
   QVector3D const outward_dir(1.0F, 0.0F, 0.0F);
@@ -54,18 +54,18 @@ TEST_F(PoseControllerCompatibilityTest, ElbowIKMatchesLegacyFunction) {
   float const lateral_offset = 0.12F;
   float const y_bias = 0.02F;
   float const outward_sign = 1.0F;
-  
+
   // Legacy approach
-  QVector3D const legacy_elbow = elbowBendTorso(shoulder, hand, outward_dir,
-                                                along_frac, lateral_offset,
-                                                y_bias, outward_sign);
-  
+  QVector3D const legacy_elbow =
+      elbowBendTorso(shoulder, hand, outward_dir, along_frac, lateral_offset,
+                     y_bias, outward_sign);
+
   // New controller approach
   HumanoidPoseController controller(pose, anim_ctx);
-  QVector3D const controller_elbow = controller.solveElbowIK(
-      false, shoulder, hand, outward_dir, along_frac, lateral_offset, y_bias,
-      outward_sign);
-  
+  QVector3D const controller_elbow =
+      controller.solveElbowIK(false, shoulder, hand, outward_dir, along_frac,
+                              lateral_offset, y_bias, outward_sign);
+
   // Should be identical
   EXPECT_TRUE(approxEqual(legacy_elbow, controller_elbow, 0.001F))
       << "Legacy: " << legacy_elbow.x() << ", " << legacy_elbow.y() << ", "
@@ -76,12 +76,12 @@ TEST_F(PoseControllerCompatibilityTest, ElbowIKMatchesLegacyFunction) {
 
 TEST_F(PoseControllerCompatibilityTest, PlaceHandAtUsesCorrectElbowIK) {
   // Verify that placeHandAt uses the same IK as direct manipulation
-  
+
   // Create a copy for legacy approach
   HumanoidPose legacy_pose = pose;
-  
+
   QVector3D const target_hand(0.30F, 1.20F, 0.80F);
-  
+
   // Legacy approach: manual IK
   legacy_pose.hand_r = target_hand;
   QVector3D right_axis = legacy_pose.shoulderR - legacy_pose.shoulderL;
@@ -90,15 +90,16 @@ TEST_F(PoseControllerCompatibilityTest, PlaceHandAtUsesCorrectElbowIK) {
   QVector3D const outward_r = right_axis;
   legacy_pose.elbowR = elbowBendTorso(legacy_pose.shoulderR, target_hand,
                                       outward_r, 0.48F, 0.12F, 0.02F, 1.0F);
-  
+
   // New controller approach
   HumanoidPoseController controller(pose, anim_ctx);
   controller.placeHandAt(false, target_hand);
-  
+
   // Hand should be at target
   EXPECT_TRUE(approxEqual(pose.hand_r, target_hand, 0.001F));
-  
-  // Elbow should be very similar (minor differences due to internal calculations)
+
+  // Elbow should be very similar (minor differences due to internal
+  // calculations)
   EXPECT_TRUE(approxEqual(pose.elbowR, legacy_pose.elbowR, 0.05F))
       << "Legacy elbow: " << legacy_pose.elbowR.x() << ", "
       << legacy_pose.elbowR.y() << ", " << legacy_pose.elbowR.z() << "\n"
@@ -108,16 +109,16 @@ TEST_F(PoseControllerCompatibilityTest, PlaceHandAtUsesCorrectElbowIK) {
 
 TEST_F(PoseControllerCompatibilityTest, KneeIKHandlesExtremeCases) {
   // Test knee IK with extreme cases to verify robustness
-  
+
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   // Very short distance (hip very close to foot)
   QVector3D const hip1(0.0F, 0.50F, 0.0F);
   QVector3D const foot1(0.05F, 0.45F, 0.05F);
   QVector3D const knee1 = controller.solveKneeIK(true, hip1, foot1, 1.0F);
   EXPECT_GE(knee1.y(), HumanProportions::GROUND_Y);
   EXPECT_LE(knee1.y(), hip1.y());
-  
+
   // Maximum reach (foot very far from hip)
   QVector3D const hip2(0.0F, 1.00F, 0.0F);
   QVector3D const foot2(0.80F, 0.0F, 0.80F);
@@ -126,11 +127,13 @@ TEST_F(PoseControllerCompatibilityTest, KneeIKHandlesExtremeCases) {
   EXPECT_LE(knee2.y(), hip2.y());
 }
 
-TEST_F(PoseControllerCompatibilityTest, KneelProducesSimilarPoseToExistingCode) {
+TEST_F(PoseControllerCompatibilityTest,
+       KneelProducesSimilarPoseToExistingCode) {
   // Compare kneel() result with typical hand-coded kneeling pose
   using HP = HumanProportions;
-  
-  // Create a reference pose with manual kneeling (similar to archer_renderer.cpp)
+
+  // Create a reference pose with manual kneeling (similar to
+  // archer_renderer.cpp)
   HumanoidPose reference_pose = pose;
   float const kneel_depth = 0.45F;
   float const pelvis_y = HP::WAIST_Y - kneel_depth;
@@ -138,42 +141,45 @@ TEST_F(PoseControllerCompatibilityTest, KneelProducesSimilarPoseToExistingCode)
   reference_pose.shoulderL.setY(HP::SHOULDER_Y - kneel_depth);
   reference_pose.shoulderR.setY(HP::SHOULDER_Y - kneel_depth);
   reference_pose.neck_base.setY(HP::NECK_BASE_Y - kneel_depth);
-  reference_pose.headPos.setY((HP::HEAD_TOP_Y + HP::CHIN_Y) * 0.5F - kneel_depth);
-  
+  reference_pose.headPos.setY((HP::HEAD_TOP_Y + HP::CHIN_Y) * 0.5F -
+                              kneel_depth);
+
   // Use controller to kneel
   HumanoidPoseController controller(pose, anim_ctx);
   controller.kneel(1.0F); // Full kneel
-  
+
   // Should be similar (allowing for controller's specific implementation)
   EXPECT_NEAR(pose.pelvisPos.y(), reference_pose.pelvisPos.y(), 0.10F);
   EXPECT_LT(pose.shoulderL.y(), HP::SHOULDER_Y); // Shoulders lowered
   EXPECT_LT(pose.shoulderR.y(), HP::SHOULDER_Y);
 }
 
-TEST_F(PoseControllerCompatibilityTest, LeanProducesReasonableUpperBodyDisplacement) {
+TEST_F(PoseControllerCompatibilityTest,
+       LeanProducesReasonableUpperBodyDisplacement) {
   // Test that lean produces sensible displacement
   using HP = HumanProportions;
-  
+
   QVector3D const original_shoulder_l = pose.shoulderL;
   QVector3D const original_shoulder_r = pose.shoulderR;
   QVector3D const original_head = pose.headPos;
-  
+
   QVector3D const lean_dir(0.0F, 0.0F, 1.0F); // Forward
   float const lean_amount = 0.8F;
-  
+
   HumanoidPoseController controller(pose, anim_ctx);
   controller.lean(lean_dir, lean_amount);
-  
+
   // Shoulders should move forward
   EXPECT_GT(pose.shoulderL.z(), original_shoulder_l.z());
   EXPECT_GT(pose.shoulderR.z(), original_shoulder_r.z());
-  
+
   // Head should move forward but less than shoulders
   EXPECT_GT(pose.headPos.z(), original_head.z());
-  float const shoulder_displacement = pose.shoulderL.z() - original_shoulder_l.z();
+  float const shoulder_displacement =
+      pose.shoulderL.z() - original_shoulder_l.z();
   float const head_displacement = pose.headPos.z() - original_head.z();
   EXPECT_LT(head_displacement, shoulder_displacement);
-  
+
   // Displacement should be proportional to lean amount
   float const expected_magnitude = 0.12F * lean_amount;
   EXPECT_NEAR(shoulder_displacement, expected_magnitude, 0.02F);
@@ -182,43 +188,46 @@ TEST_F(PoseControllerCompatibilityTest, LeanProducesReasonableUpperBodyDisplacem
 TEST_F(PoseControllerCompatibilityTest, CanRecreateBowAimingPose) {
   // Recreate a typical bow aiming pose using the controller
   using HP = HumanProportions;
-  
+
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   // Archer kneel and aim
   controller.kneel(1.0F);
   controller.lean(QVector3D(0.0F, 0.0F, 1.0F), 0.2F); // Slight forward lean
-  
+
   // Position hands for bow
   float const lowered_shoulder_y = pose.shoulderL.y();
-  controller.placeHandAt(true, QVector3D(-0.15F, lowered_shoulder_y + 0.30F, 0.55F));
-  controller.placeHandAt(false, QVector3D(0.12F, pose.shoulderR.y() + 0.15F, 0.10F));
-  
+  controller.placeHandAt(true,
+                         QVector3D(-0.15F, lowered_shoulder_y + 0.30F, 0.55F));
+  controller.placeHandAt(false,
+                         QVector3D(0.12F, pose.shoulderR.y() + 0.15F, 0.10F));
+
   // Verify pose is in a reasonable configuration
-  EXPECT_LT(pose.pelvisPos.y(), HP::WAIST_Y); // Kneeling
+  EXPECT_LT(pose.pelvisPos.y(), HP::WAIST_Y);    // Kneeling
   EXPECT_GT(pose.handL.y(), pose.shoulderL.y()); // Left hand raised
-  EXPECT_GT(pose.handL.z(), 0.0F); // Left hand forward
+  EXPECT_GT(pose.handL.z(), 0.0F);               // Left hand forward
   EXPECT_LT(pose.hand_r.z(), pose.handL.z()); // Right hand back (drawing bow)
 }
 
 TEST_F(PoseControllerCompatibilityTest, CanRecreateMeleeAttackPose) {
   // Recreate a typical melee attack pose using the controller
   using HP = HumanProportions;
-  
+
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   // Spearman thrust pose
   controller.lean(QVector3D(0.0F, 0.0F, 1.0F), 0.5F); // Forward lean
-  
+
   // Thrust position
   QVector3D const thrust_hand(0.32F, HP::SHOULDER_Y + 0.10F, 0.90F);
   controller.placeHandAt(false, thrust_hand);
-  
+
   // Support hand
-  controller.placeHandAt(true, QVector3D(-0.05F, HP::SHOULDER_Y + 0.03F, 0.53F));
-  
+  controller.placeHandAt(true,
+                         QVector3D(-0.05F, HP::SHOULDER_Y + 0.03F, 0.53F));
+
   // Verify thrust pose characteristics
-  EXPECT_GT(pose.hand_r.z(), 0.80F); // Hand extended forward
-  EXPECT_GT(pose.shoulderL.z(), 0.0F); // Body leaning forward
+  EXPECT_GT(pose.hand_r.z(), 0.80F);              // Hand extended forward
+  EXPECT_GT(pose.shoulderL.z(), 0.0F);            // Body leaning forward
   EXPECT_GT(pose.elbowR.z(), pose.shoulderR.z()); // Elbow extended
 }

+ 56 - 57
tests/render/pose_controller_test.cpp

@@ -1,9 +1,9 @@
-#include "render/humanoid/pose_controller.h"
 #include "render/humanoid/humanoid_specs.h"
+#include "render/humanoid/pose_controller.h"
 #include "render/humanoid/rig.h"
 #include <QVector3D>
-#include <gtest/gtest.h>
 #include <cmath>
+#include <gtest/gtest.h>
 
 using namespace Render::GL;
 
@@ -39,7 +39,7 @@ protected:
 
   HumanoidPose pose;
   HumanoidAnimationContext anim_ctx;
-  
+
   // Helper to check if a position is approximately equal
   bool approxEqual(const QVector3D &a, const QVector3D &b,
                    float epsilon = 0.01F) {
@@ -58,12 +58,12 @@ TEST_F(HumanoidPoseControllerTest, ConstructorInitializesCorrectly) {
 
 TEST_F(HumanoidPoseControllerTest, StandIdleDoesNotModifyPose) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const original_pelvis = pose.pelvisPos;
   QVector3D const original_shoulder_l = pose.shoulderL;
-  
+
   controller.standIdle();
-  
+
   // standIdle should be a no-op, keeping pose unchanged
   EXPECT_TRUE(approxEqual(pose.pelvisPos, original_pelvis));
   EXPECT_TRUE(approxEqual(pose.shoulderL, original_shoulder_l));
@@ -71,14 +71,14 @@ TEST_F(HumanoidPoseControllerTest, StandIdleDoesNotModifyPose) {
 
 TEST_F(HumanoidPoseControllerTest, KneelLowersPelvis) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   float const original_pelvis_y = pose.pelvisPos.y();
-  
+
   controller.kneel(0.5F);
-  
+
   // Kneeling should lower the pelvis
   EXPECT_LT(pose.pelvisPos.y(), original_pelvis_y);
-  
+
   // Pelvis should be lowered by approximately depth * 0.40F
   float const expected_offset = 0.5F * 0.40F;
   EXPECT_NEAR(pose.pelvisPos.y(), HumanProportions::WAIST_Y - expected_offset,
@@ -87,36 +87,36 @@ TEST_F(HumanoidPoseControllerTest, KneelLowersPelvis) {
 
 TEST_F(HumanoidPoseControllerTest, KneelFullDepthTouchesGroundWithKnee) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   controller.kneel(1.0F);
-  
+
   // At full kneel, left knee should be very close to ground
   EXPECT_NEAR(pose.knee_l.y(), HumanProportions::GROUND_Y + 0.07F, 0.02F);
-  
+
   // Pelvis should be lowered significantly
   EXPECT_LT(pose.pelvisPos.y(), HumanProportions::WAIST_Y - 0.35F);
 }
 
 TEST_F(HumanoidPoseControllerTest, KneelZeroDepthKeepsStanding) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   float const original_pelvis_y = pose.pelvisPos.y();
-  
+
   controller.kneel(0.0F);
-  
+
   // Zero depth should keep pelvis at original height
   EXPECT_NEAR(pose.pelvisPos.y(), original_pelvis_y, 0.01F);
 }
 
 TEST_F(HumanoidPoseControllerTest, LeanMovesUpperBody) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const original_shoulder_l = pose.shoulderL;
   QVector3D const original_shoulder_r = pose.shoulderR;
   QVector3D const lean_direction(0.0F, 0.0F, 1.0F); // Forward
-  
+
   controller.lean(lean_direction, 0.5F);
-  
+
   // Shoulders should move forward when leaning forward
   EXPECT_GT(pose.shoulderL.z(), original_shoulder_l.z());
   EXPECT_GT(pose.shoulderR.z(), original_shoulder_r.z());
@@ -124,38 +124,38 @@ TEST_F(HumanoidPoseControllerTest, LeanMovesUpperBody) {
 
 TEST_F(HumanoidPoseControllerTest, LeanZeroAmountNoChange) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const original_shoulder_l = pose.shoulderL;
   QVector3D const lean_direction(1.0F, 0.0F, 0.0F); // Right
-  
+
   controller.lean(lean_direction, 0.0F);
-  
+
   // Zero amount should keep shoulders unchanged
   EXPECT_TRUE(approxEqual(pose.shoulderL, original_shoulder_l));
 }
 
 TEST_F(HumanoidPoseControllerTest, PlaceHandAtSetsHandPosition) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const target_position(0.30F, 1.20F, 0.80F);
-  
+
   controller.placeHandAt(false, target_position); // Right hand
-  
+
   // Hand should be at target position
   EXPECT_TRUE(approxEqual(pose.hand_r, target_position));
 }
 
 TEST_F(HumanoidPoseControllerTest, PlaceHandAtComputesElbow) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const target_position(0.30F, 1.20F, 0.80F);
   QVector3D const original_elbow = pose.elbowR;
-  
+
   controller.placeHandAt(false, target_position); // Right hand
-  
+
   // Elbow should be recomputed (different from original)
   EXPECT_FALSE(approxEqual(pose.elbowR, original_elbow));
-  
+
   // Elbow should be between shoulder and hand
   float const shoulder_to_elbow_dist = (pose.elbowR - pose.shoulderR).length();
   float const elbow_to_hand_dist = (target_position - pose.elbowR).length();
@@ -165,18 +165,17 @@ TEST_F(HumanoidPoseControllerTest, PlaceHandAtComputesElbow) {
 
 TEST_F(HumanoidPoseControllerTest, SolveElbowIKReturnsValidPosition) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const shoulder = pose.shoulderR;
   QVector3D const hand(0.35F, 1.15F, 0.75F);
   QVector3D const outward_dir(1.0F, 0.0F, 0.0F);
-  
-  QVector3D const elbow = controller.solveElbowIK(false, shoulder, hand,
-                                                  outward_dir, 0.45F, 0.15F,
-                                                  0.0F, 1.0F);
-  
+
+  QVector3D const elbow = controller.solveElbowIK(
+      false, shoulder, hand, outward_dir, 0.45F, 0.15F, 0.0F, 1.0F);
+
   // Elbow should be somewhere between shoulder and hand
   EXPECT_GT(elbow.length(), 0.0F);
-  
+
   // Distance from shoulder to elbow should be reasonable
   float const shoulder_elbow_dist = (elbow - shoulder).length();
   EXPECT_GT(shoulder_elbow_dist, 0.05F);
@@ -185,31 +184,31 @@ TEST_F(HumanoidPoseControllerTest, SolveElbowIKReturnsValidPosition) {
 
 TEST_F(HumanoidPoseControllerTest, SolveKneeIKReturnsValidPosition) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const hip(0.10F, 0.93F, 0.0F);
   QVector3D const foot(0.10F, 0.0F, 0.05F);
   float const height_scale = 1.0F;
-  
+
   QVector3D const knee = controller.solveKneeIK(false, hip, foot, height_scale);
-  
+
   // Knee should be between hip and foot (in Y)
   EXPECT_LT(knee.y(), hip.y());
   EXPECT_GT(knee.y(), foot.y());
-  
+
   // Knee should not be below ground
   EXPECT_GE(knee.y(), HumanProportions::GROUND_Y);
 }
 
 TEST_F(HumanoidPoseControllerTest, SolveKneeIKPreventsGroundPenetration) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   // Set up a scenario where IK would put knee below ground
-  QVector3D const hip(0.0F, 0.30F, 0.0F); // Very low hip
+  QVector3D const hip(0.0F, 0.30F, 0.0F);   // Very low hip
   QVector3D const foot(0.50F, 0.0F, 0.50F); // Far foot
   float const height_scale = 1.0F;
-  
+
   QVector3D const knee = controller.solveKneeIK(true, hip, foot, height_scale);
-  
+
   // Knee should be at or above the floor threshold
   float const min_knee_y = HumanProportions::GROUND_Y + pose.footYOffset * 0.5F;
   EXPECT_GE(knee.y(), min_knee_y - 0.001F); // Small epsilon for floating point
@@ -217,52 +216,52 @@ TEST_F(HumanoidPoseControllerTest, SolveKneeIKPreventsGroundPenetration) {
 
 TEST_F(HumanoidPoseControllerTest, PlaceHandAtLeftHandWorks) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const target_position(-0.40F, 1.30F, 0.60F);
-  
+
   controller.placeHandAt(true, target_position); // Left hand
-  
+
   // Left hand should be at target position
   EXPECT_TRUE(approxEqual(pose.handL, target_position));
-  
+
   // Left elbow should be computed
   EXPECT_GT((pose.elbowL - pose.shoulderL).length(), 0.0F);
 }
 
 TEST_F(HumanoidPoseControllerTest, KneelClampsBounds) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   // Test clamping of depth > 1.0
   controller.kneel(1.5F);
   float const max_kneel_pelvis_y = pose.pelvisPos.y();
-  
+
   // Reset pose
   SetUp();
   HumanoidPoseController controller2(pose, anim_ctx);
-  
+
   // Test depth = 1.0
   controller2.kneel(1.0F);
-  
+
   // Should be same as clamped 1.5F
   EXPECT_NEAR(pose.pelvisPos.y(), max_kneel_pelvis_y, 0.001F);
 }
 
 TEST_F(HumanoidPoseControllerTest, LeanClampsBounds) {
   HumanoidPoseController controller(pose, anim_ctx);
-  
+
   QVector3D const lean_direction(0.0F, 0.0F, 1.0F);
-  
+
   // Test clamping of amount > 1.0
   controller.lean(lean_direction, 1.5F);
   float const max_lean_z = pose.shoulderL.z();
-  
+
   // Reset pose
   SetUp();
   HumanoidPoseController controller2(pose, anim_ctx);
-  
+
   // Test amount = 1.0
   controller2.lean(lean_direction, 1.0F);
-  
+
   // Should be same as clamped 1.5F
   EXPECT_NEAR(pose.shoulderL.z(), max_lean_z, 0.001F);
 }