Adam Djellouli 1 month ago
parent
commit
3270b1503e
40 changed files with 1238 additions and 262 deletions
  1. 118 0
      assets/shaders/carthage_light_helmet.frag
  2. 42 0
      assets/shaders/carthage_light_helmet.vert
  3. 169 0
      assets/shaders/chainmail_armor.frag
  4. 34 0
      assets/shaders/chainmail_armor.vert
  5. 1 1
      render/entity/arrow_vfx_renderer.cpp
  6. 2 2
      render/entity/barracks_flag_renderer.h
  7. 5 5
      render/entity/barracks_renderer.cpp
  8. 1 1
      render/entity/barracks_renderer.h
  9. 6 6
      render/entity/nations/carthage/archer_renderer.cpp
  10. 67 67
      render/entity/nations/carthage/barracks_renderer.cpp
  11. 1 1
      render/entity/nations/carthage/barracks_renderer.h
  12. 6 6
      render/entity/nations/carthage/horse_swordsman_renderer.cpp
  13. 6 6
      render/entity/nations/carthage/spearman_renderer.cpp
  14. 7 7
      render/entity/nations/carthage/swordsman_renderer.cpp
  15. 6 6
      render/entity/nations/kingdom/archer_renderer.cpp
  16. 38 38
      render/entity/nations/kingdom/barracks_renderer.cpp
  17. 1 1
      render/entity/nations/kingdom/barracks_renderer.h
  18. 6 6
      render/entity/nations/kingdom/horse_swordsman_renderer.cpp
  19. 6 6
      render/entity/nations/kingdom/spearman_renderer.cpp
  20. 7 7
      render/entity/nations/kingdom/swordsman_renderer.cpp
  21. 6 6
      render/entity/nations/roman/archer_renderer.cpp
  22. 38 38
      render/entity/nations/roman/barracks_renderer.cpp
  23. 1 1
      render/entity/nations/roman/barracks_renderer.h
  24. 6 6
      render/entity/nations/roman/horse_swordsman_renderer.cpp
  25. 6 6
      render/entity/nations/roman/spearman_renderer.cpp
  26. 7 7
      render/entity/nations/roman/swordsman_renderer.cpp
  27. 2 2
      render/entity/registry.cpp
  28. 1 1
      render/entity/registry.h
  29. 252 0
      render/equipment/armor/chainmail_armor.cpp
  30. 48 0
      render/equipment/armor/chainmail_armor.h
  31. 264 0
      render/equipment/helmets/carthage_light_helmet.cpp
  32. 49 0
      render/equipment/helmets/carthage_light_helmet.h
  33. 1 1
      render/gl/backend.cpp
  34. 1 1
      render/gl/backend/backend_impl.h
  35. 1 1
      render/gl/backend/cylinder_pipeline.cpp
  36. 1 1
      render/gl/backend/cylinder_pipeline.h
  37. 1 1
      render/gl/persistent_buffer_example.cpp
  38. 9 9
      render/horse/rig.cpp
  39. 10 10
      render/humanoid/rig.cpp
  40. 5 5
      render/humanoid/rig.h

+ 118 - 0
assets/shaders/carthage_light_helmet.frag

@@ -0,0 +1,118 @@
+#version 330 core
+
+in vec3 v_normal;
+in vec3 v_worldPos;
+in vec3 v_viewDir;
+in vec2 v_texCoord;
+in float v_metallic;
+in float v_roughness;
+
+uniform vec3 u_color;
+uniform float u_alpha;
+uniform vec3 u_lightDir; // Sun direction
+uniform vec3 u_lightColor;
+uniform vec3 u_ambientColor;
+
+out vec4 FragColor;
+
+// Fresnel-Schlick approximation for metallic reflection
+vec3 fresnelSchlick(float cosTheta, vec3 F0) {
+  return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
+}
+
+// GGX normal distribution for specular highlights
+float distributionGGX(vec3 N, vec3 H, float roughness) {
+  float a = roughness * roughness;
+  float a2 = a * a;
+  float NdotH = max(dot(N, H), 0.0);
+  float NdotH2 = NdotH * NdotH;
+  
+  float denom = (NdotH2 * (a2 - 1.0) + 1.0);
+  denom = 3.14159265 * denom * denom;
+  
+  return a2 / max(denom, 0.0001);
+}
+
+// Procedural bronze oxidation/patina
+vec3 bronzePatina(vec3 baseColor, vec3 worldPos) {
+  // Green-blue patina in crevices and lower areas
+  float patina_noise = fract(sin(dot(worldPos.xz, vec2(12.9898, 78.233))) * 43758.5453);
+  float patina_amount = smoothstep(1.5, 1.7, worldPos.y) * 0.3 * patina_noise;
+  
+  vec3 patina_color = vec3(0.2, 0.55, 0.45); // Verdigris green
+  return mix(baseColor, patina_color, patina_amount);
+}
+
+// Hammered metal texture
+float hammeredTexture(vec2 uv) {
+  vec2 id = floor(uv * 32.0);
+  float n = fract(sin(dot(id, vec2(12.9898, 78.233))) * 43758.5453);
+  
+  vec2 local = fract(uv * 32.0) - 0.5;
+  float dist = length(local);
+  
+  // Circular hammer marks
+  float hammer = smoothstep(0.4, 0.3, dist) * (0.5 + n * 0.5);
+  return hammer * 0.15;
+}
+
+// Rivet detail
+float rivetDetail(vec2 uv) {
+  vec2 rivet_grid = fract(uv * 6.0) - 0.5;
+  float rivet_dist = length(rivet_grid);
+  
+  float rivet = smoothstep(0.08, 0.05, rivet_dist);
+  rivet *= smoothstep(0.12, 0.10, rivet_dist); // Ring around rivet
+  
+  return rivet * 0.25;
+}
+
+void main() {
+  vec3 N = normalize(v_normal);
+  vec3 V = normalize(v_viewDir);
+  vec3 L = normalize(u_lightDir);
+  vec3 H = normalize(V + L);
+  
+  // Base bronze color with procedural weathering
+  vec3 baseColor = bronzePatina(u_color, v_worldPos);
+  
+  // Add hammered texture detail
+  float hammer = hammeredTexture(v_texCoord);
+  baseColor = mix(baseColor, baseColor * 0.85, hammer);
+  
+  // Add rivet highlights
+  float rivets = rivetDetail(v_texCoord);
+  baseColor = mix(baseColor, baseColor * 1.3, rivets);
+  
+  // PBR lighting calculation
+  vec3 F0 = mix(vec3(0.04), baseColor, v_metallic);
+  vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
+  
+  // Specular component
+  float NDF = distributionGGX(N, H, v_roughness);
+  float NdotL = max(dot(N, L), 0.0);
+  float NdotV = max(dot(N, V), 0.0);
+  
+  vec3 specular = NDF * F / max(4.0 * NdotV * NdotL, 0.001);
+  
+  // Diffuse component
+  vec3 kD = (vec3(1.0) - F) * (1.0 - v_metallic);
+  vec3 diffuse = kD * baseColor / 3.14159265;
+  
+  // Combine lighting
+  vec3 ambient = u_ambientColor * baseColor * 0.3;
+  vec3 radiance = u_lightColor * NdotL;
+  vec3 color = ambient + (diffuse + specular) * radiance;
+  
+  // Edge wear (brighter on edges from polishing)
+  float edge_factor = pow(1.0 - NdotV, 3.0);
+  color = mix(color, color * 1.4, edge_factor * 0.3);
+  
+  // Tone mapping
+  color = color / (color + vec3(1.0));
+  
+  // Gamma correction
+  color = pow(color, vec3(1.0 / 2.2));
+  
+  FragColor = vec4(color, u_alpha);
+}

+ 42 - 0
assets/shaders/carthage_light_helmet.vert

@@ -0,0 +1,42 @@
+#version 330 core
+
+layout(location = 0) in vec3 a_position;
+layout(location = 1) in vec3 a_normal;
+layout(location = 2) in vec2 a_texCoord;
+
+uniform mat4 u_mvp;
+uniform mat4 u_model;
+uniform mat3 u_normalMatrix;
+
+out vec3 v_normal;
+out vec3 v_worldPos;
+out vec3 v_viewDir;
+out vec2 v_texCoord;
+out float v_metallic;
+out float v_roughness;
+
+void main() {
+  vec4 worldPos = u_model * vec4(a_position, 1.0);
+  v_worldPos = worldPos.xyz;
+  v_normal = normalize(u_normalMatrix * a_normal);
+  v_texCoord = a_texCoord;
+  
+  // Camera at approximate position for view direction
+  vec3 cameraPos = vec3(0.0, 1.5, 5.0);
+  v_viewDir = normalize(cameraPos - v_worldPos);
+  
+  // Material properties based on position
+  // Bronze helmet: high metallic, medium roughness
+  if (v_worldPos.y > 1.6) {
+    v_metallic = 0.85; // Bronze
+    v_roughness = 0.35; // Polished but weathered
+  } else if (v_worldPos.y > 1.5) {
+    v_metallic = 0.75; // Crest mount
+    v_roughness = 0.45;
+  } else {
+    v_metallic = 0.65; // Cheek guards
+    v_roughness = 0.5;
+  }
+  
+  gl_Position = u_mvp * vec4(a_position, 1.0);
+}

+ 169 - 0
assets/shaders/chainmail_armor.frag

@@ -0,0 +1,169 @@
+#version 330 core
+
+in vec3 v_normal;
+in vec3 v_worldPos;
+in vec3 v_viewDir;
+in vec2 v_texCoord;
+in float v_ringPhase;
+
+uniform vec3 u_color;
+uniform float u_alpha;
+uniform vec3 u_lightDir;
+uniform vec3 u_lightColor;
+uniform vec3 u_ambientColor;
+uniform float u_rustAmount; // 0.0 = pristine, 1.0 = heavily rusted
+
+out vec4 FragColor;
+
+// Hash function for procedural noise
+float hash(vec2 p) {
+  vec3 p3 = fract(vec3(p.xyx) * 0.1031);
+  p3 += dot(p3, p3.yzx + 33.33);
+  return fract((p3.x + p3.y) * p3.z);
+}
+
+// 2D noise
+float noise(vec2 p) {
+  vec2 i = floor(p);
+  vec2 f = fract(p);
+  f = f * f * (3.0 - 2.0 * f);
+  
+  float a = hash(i);
+  float b = hash(i + vec2(1.0, 0.0));
+  float c = hash(i + vec2(0.0, 1.0));
+  float d = hash(i + vec2(1.0, 1.0));
+  
+  return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
+}
+
+// Chainmail ring pattern - interlocking rings
+float chainmailRingPattern(vec2 uv, float phase) {
+  vec2 uv_scaled = uv * 64.0; // Ring density
+  
+  // Apply row offset for interlocking
+  uv_scaled.x += phase * 0.5;
+  
+  vec2 grid = fract(uv_scaled) - 0.5;
+  float ring_dist = length(grid);
+  
+  // Outer ring
+  float outer_ring = smoothstep(0.45, 0.40, ring_dist) - smoothstep(0.35, 0.30, ring_dist);
+  
+  // Inner ring (creates depth)
+  float inner_ring = smoothstep(0.32, 0.28, ring_dist) - smoothstep(0.25, 0.20, ring_dist);
+  
+  // Combine rings
+  float ring = outer_ring + inner_ring * 0.5;
+  
+  // Add ring overlap highlights (where rings interlock)
+  vec2 overlap_grid = fract(uv_scaled + vec2(0.5, 0.0)) - 0.5;
+  float overlap_dist = length(overlap_grid);
+  float overlap = smoothstep(0.25, 0.22, overlap_dist) * 0.3;
+  
+  return clamp(ring + overlap, 0.0, 1.0);
+}
+
+// Rust and weathering
+vec3 applyRust(vec3 baseColor, vec3 worldPos, float rustAmount) {
+  // Rust color palette
+  vec3 rust_dark = vec3(0.35, 0.15, 0.10); // Dark rust/brown
+  vec3 rust_bright = vec3(0.65, 0.35, 0.20); // Orange rust
+  vec3 rust_green = vec3(0.25, 0.40, 0.35); // Green oxidation
+  
+  // Procedural rust distribution
+  float rust_noise1 = noise(worldPos.xz * 20.0);
+  float rust_noise2 = noise(worldPos.xy * 15.0);
+  float rust_noise3 = noise(worldPos.yz * 18.0);
+  
+  float combined_noise = (rust_noise1 + rust_noise2 + rust_noise3) / 3.0;
+  
+  // More rust in lower areas (gravity/water accumulation)
+  float height_factor = clamp(1.0 - worldPos.y * 0.6, 0.0, 1.0);
+  
+  // Total rust amount
+  float total_rust = combined_noise * rustAmount * height_factor;
+  total_rust = clamp(total_rust, 0.0, 1.0);
+  
+  // Mix rust colors
+  vec3 rust_mix = mix(rust_dark, rust_bright, rust_noise1);
+  rust_mix = mix(rust_mix, rust_green, rust_noise2 * 0.3);
+  
+  return mix(baseColor, rust_mix, total_rust);
+}
+
+// Ring highlights and shadows
+float ringAO(vec2 uv, float phase) {
+  vec2 uv_scaled = uv * 64.0;
+  uv_scaled.x += phase * 0.5;
+  
+  vec2 grid = fract(uv_scaled) - 0.5;
+  float dist = length(grid);
+  
+  // Ambient occlusion in ring valleys
+  float ao = smoothstep(0.15, 0.35, dist);
+  return ao;
+}
+
+// Fresnel for metal reflection
+float fresnel(vec3 viewDir, vec3 normal, float power) {
+  return pow(1.0 - max(dot(viewDir, normal), 0.0), power);
+}
+
+void main() {
+  vec3 N = normalize(v_normal);
+  vec3 V = normalize(v_viewDir);
+  vec3 L = normalize(u_lightDir);
+  vec3 H = normalize(V + L);
+  
+  // Base steel/iron color
+  vec3 baseColor = u_color;
+  
+  // Apply chainmail ring pattern
+  float ringPattern = chainmailRingPattern(v_texCoord, v_ringPhase);
+  vec3 ringColor = mix(baseColor * 0.6, baseColor * 1.2, ringPattern);
+  
+  // Apply ambient occlusion from ring structure
+  float ao = ringAO(v_texCoord, v_ringPhase);
+  ringColor *= mix(0.7, 1.0, ao);
+  
+  // Apply rust/weathering
+  ringColor = applyRust(ringColor, v_worldPos, u_rustAmount);
+  
+  // Lighting calculation
+  float NdotL = max(dot(N, L), 0.0);
+  float NdotH = max(dot(N, H), 0.0);
+  
+  // Diffuse
+  vec3 diffuse = ringColor * NdotL;
+  
+  // Specular (metallic)
+  float roughness = mix(0.3, 0.8, u_rustAmount); // More rust = rougher
+  float specular_power = mix(128.0, 16.0, roughness);
+  float specular = pow(NdotH, specular_power) * (1.0 - u_rustAmount * 0.7);
+  
+  // Fresnel rim lighting
+  float rim = fresnel(V, N, 3.0) * 0.4;
+  
+  // Ambient
+  vec3 ambient = u_ambientColor * ringColor * 0.4;
+  
+  // Combine
+  vec3 color = ambient + (diffuse + vec3(specular) * 0.8) * u_lightColor;
+  color += vec3(rim) * u_lightColor;
+  
+  // Ring edge highlights
+  float edge_highlight = ringPattern * specular * 0.5;
+  color += vec3(edge_highlight);
+  
+  // Subtle chainmail shimmer (from ring overlaps)
+  float shimmer = noise(v_texCoord * 80.0 + v_worldPos.xy) * ringPattern * 0.15;
+  color += vec3(shimmer);
+  
+  // Tone mapping
+  color = color / (color + vec3(1.0));
+  
+  // Gamma correction
+  color = pow(color, vec3(1.0 / 2.2));
+  
+  FragColor = vec4(color, u_alpha);
+}

+ 34 - 0
assets/shaders/chainmail_armor.vert

@@ -0,0 +1,34 @@
+#version 330 core
+
+layout(location = 0) in vec3 a_position;
+layout(location = 1) in vec3 a_normal;
+layout(location = 2) in vec2 a_texCoord;
+
+uniform mat4 u_mvp;
+uniform mat4 u_model;
+uniform mat3 u_normalMatrix;
+uniform float u_time; // For dynamic ring shimmer
+
+out vec3 v_normal;
+out vec3 v_worldPos;
+out vec3 v_viewDir;
+out vec2 v_texCoord;
+out float v_ringPhase; // For chainmail ring pattern
+
+void main() {
+  vec4 worldPos = u_model * vec4(a_position, 1.0);
+  v_worldPos = worldPos.xyz;
+  v_normal = normalize(u_normalMatrix * a_normal);
+  v_texCoord = a_texCoord;
+  
+  // Camera position
+  vec3 cameraPos = vec3(0.0, 1.5, 5.0);
+  v_viewDir = normalize(cameraPos - v_worldPos);
+  
+  // Ring phase for interlocking pattern
+  // Creates alternating offset rows for realistic chainmail
+  float rowIndex = floor(v_worldPos.y * 50.0);
+  v_ringPhase = mod(rowIndex, 2.0);
+  
+  gl_Position = u_mvp * vec4(a_position, 1.0);
+}

+ 1 - 1
render/entity/arrow_vfx_renderer.cpp

@@ -372,7 +372,7 @@ static inline void drawBowAndArrow(const DrawContext &p, ISubmitter &out,
 }
 
 void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
-  registry.registerRenderer(
+  registry.register_renderer(
       "archer", [](const DrawContext &p, ISubmitter &out) {
         QVector3D tunic(0.8F, 0.9F, 1.0F);
         Engine::Core::UnitComponent *unit = nullptr;

+ 2 - 2
render/entity/barracks_flag_renderer.h

@@ -24,7 +24,7 @@ struct FlagColors {
   QVector3D woodDark;
 };
 
-inline void drawRallyFlagIfAny(const DrawContext &p, ISubmitter &out,
+inline void draw_rally_flag_if_any(const DrawContext &p, ISubmitter &out,
                                Texture *white, const FlagColors &colors) {
   if (auto *prod =
           p.entity->getComponent<Engine::Core::ProductionComponent>()) {
@@ -80,7 +80,7 @@ struct CaptureColors {
   float loweringOffset;
 };
 
-inline CaptureColors getCaptureColors(const DrawContext &p,
+inline CaptureColors get_capture_colors(const DrawContext &p,
                                       const QVector3D &baseTeamColor,
                                       const QVector3D &baseTeamTrim,
                                       float maxLowering = 0.0F) {

+ 5 - 5
render/entity/barracks_renderer.cpp

@@ -8,13 +8,13 @@
 
 namespace Render::GL {
 
-void registerBarracksRenderer(EntityRendererRegistry &registry) {
+void register_barracks_renderer(EntityRendererRegistry &registry) {
 
-  Kingdom::registerBarracksRenderer(registry);
-  Roman::registerBarracksRenderer(registry);
-  Carthage::registerBarracksRenderer(registry);
+  Kingdom::register_barracks_renderer(registry);
+  Roman::register_barracks_renderer(registry);
+  Carthage::register_barracks_renderer(registry);
 
-  registry.registerRenderer(
+  registry.register_renderer(
       "barracks", [&registry](const DrawContext &p, ISubmitter &out) {
         if (p.entity == nullptr) {
           return;

+ 1 - 1
render/entity/barracks_renderer.h

@@ -6,6 +6,6 @@ class EntityRendererRegistry;
 
 namespace Render::GL {
 
-void registerBarracksRenderer(EntityRendererRegistry &registry);
+void register_barracks_renderer(EntityRendererRegistry &registry);
 
 }

+ 6 - 6
render/entity/nations/carthage/archer_renderer.cpp

@@ -81,12 +81,12 @@ using Render::GL::Humanoid::saturate_color;
 
 class ArcherRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
 
     return {1.15F, 1.02F, 0.75F};
   }
 
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -161,7 +161,7 @@ public:
     v.weathering = 0.40F + nextRand(beard_seed) * 0.40F;
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -291,7 +291,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
     using HP = HumanProportions;
 
@@ -316,7 +316,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     if (resolve_style(ctx).show_armor) {
@@ -385,7 +385,7 @@ private:
 void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_archer_styles_registered();
   static ArcherRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/carthage/archer", [](const DrawContext &ctx, ISubmitter &out) {
         static ArcherRenderer const static_renderer;
         Shader *archer_shader = nullptr;

+ 67 - 67
render/entity/nations/carthage/barracks_renderer.cpp

@@ -38,7 +38,7 @@ struct CarthagePalette {
   QVector3D team_trim{0.48F, 0.54F, 0.60F};
 };
 
-inline auto makePalette(const QVector3D &team) -> CarthagePalette {
+inline auto make_palette(const QVector3D &team) -> CarthagePalette {
   CarthagePalette p;
   p.team = clampVec01(team);
   p.team_trim =
@@ -46,7 +46,7 @@ inline auto makePalette(const QVector3D &team) -> CarthagePalette {
   return p;
 }
 
-inline void drawBox(ISubmitter &out, Mesh *unit, Texture *white,
+inline void draw_box(ISubmitter &out, Mesh *unit, Texture *white,
                     const QMatrix4x4 &model, const QVector3D &pos,
                     const QVector3D &size, const QVector3D &color) {
   QMatrix4x4 m = model;
@@ -55,33 +55,33 @@ inline void drawBox(ISubmitter &out, Mesh *unit, Texture *white,
   out.mesh(unit, m, color, white, 1.0F);
 }
 
-inline void drawCyl(ISubmitter &out, const QMatrix4x4 &model,
+inline void draw_cyl(ISubmitter &out, const QMatrix4x4 &model,
                     const QVector3D &a, const QVector3D &b, float r,
                     const QVector3D &color, Texture *white) {
   out.mesh(getUnitCylinder(), model * cylinderBetween(a, b, r), color, white,
            1.0F);
 }
 
-void drawPlatform(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_platform(const DrawContext &p, ISubmitter &out, Mesh *unit,
                   Texture *white, const CarthagePalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.08F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.08F, 0.0F),
           QVector3D(2.0F, 0.08F, 1.8F), c.limestone_dark);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.18F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.18F, 0.0F),
           QVector3D(1.8F, 0.02F, 1.6F), c.limestone);
 
   for (float x = -1.5F; x <= 1.5F; x += 0.35F) {
     for (float z = -1.3F; z <= 1.3F; z += 0.35F) {
       if (fabsf(x) > 0.6F || fabsf(z) > 0.5F) {
-        drawBox(out, unit, white, p.model, QVector3D(x, 0.21F, z),
+        draw_box(out, unit, white, p.model, QVector3D(x, 0.21F, z),
                 QVector3D(0.15F, 0.01F, 0.15F), c.terracotta);
       }
     }
   }
 }
 
-void drawColonnade(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_colonnade(const DrawContext &p, ISubmitter &out, Mesh *unit,
                    Texture *white, const CarthagePalette &c) {
   float const col_height = 1.6F;
   float const col_radius = 0.10F;
@@ -90,17 +90,17 @@ void drawColonnade(const DrawContext &p, ISubmitter &out, Mesh *unit,
     float const x = -1.25F + float(i) * 0.5F;
     float const z = 1.4F;
 
-    drawBox(out, unit, white, p.model, QVector3D(x, 0.25F, z),
+    draw_box(out, unit, white, p.model, QVector3D(x, 0.25F, z),
             QVector3D(col_radius * 1.2F, 0.05F, col_radius * 1.2F), c.marble);
 
-    drawCyl(out, p.model, QVector3D(x, 0.2F, z),
+    draw_cyl(out, p.model, QVector3D(x, 0.2F, z),
             QVector3D(x, 0.2F + col_height, z), col_radius, c.limestone, white);
 
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(x, 0.2F + col_height + 0.05F, z),
             QVector3D(col_radius * 1.5F, 0.08F, col_radius * 1.5F), c.marble);
 
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(x, 0.2F + col_height + 0.12F, z),
             QVector3D(col_radius * 1.3F, 0.04F, col_radius * 1.3F), c.gold);
   }
@@ -109,107 +109,107 @@ void drawColonnade(const DrawContext &p, ISubmitter &out, Mesh *unit,
     float const z = -1.0F + float(i) * 1.0F;
 
     float const x_left = -1.6F;
-    drawBox(out, unit, white, p.model, QVector3D(x_left, 0.25F, z),
+    draw_box(out, unit, white, p.model, QVector3D(x_left, 0.25F, z),
             QVector3D(col_radius * 1.2F, 0.05F, col_radius * 1.2F), c.marble);
-    drawCyl(out, p.model, QVector3D(x_left, 0.2F, z),
+    draw_cyl(out, p.model, QVector3D(x_left, 0.2F, z),
             QVector3D(x_left, 0.2F + col_height, z), col_radius, c.limestone,
             white);
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(x_left, 0.2F + col_height + 0.05F, z),
             QVector3D(col_radius * 1.5F, 0.08F, col_radius * 1.5F), c.marble);
 
     float const x_right = 1.6F;
-    drawBox(out, unit, white, p.model, QVector3D(x_right, 0.25F, z),
+    draw_box(out, unit, white, p.model, QVector3D(x_right, 0.25F, z),
             QVector3D(col_radius * 1.2F, 0.05F, col_radius * 1.2F), c.marble);
-    drawCyl(out, p.model, QVector3D(x_right, 0.2F, z),
+    draw_cyl(out, p.model, QVector3D(x_right, 0.2F, z),
             QVector3D(x_right, 0.2F + col_height, z), col_radius, c.limestone,
             white);
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(x_right, 0.2F + col_height + 0.05F, z),
             QVector3D(col_radius * 1.5F, 0.08F, col_radius * 1.5F), c.marble);
   }
 }
 
-void drawCentralCourtyard(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_central_courtyard(const DrawContext &p, ISubmitter &out, Mesh *unit,
                           Texture *white, const CarthagePalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.22F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.22F, 0.0F),
           QVector3D(1.3F, 0.01F, 1.1F), c.limestone_shade);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.24F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.24F, 0.0F),
           QVector3D(0.7F, 0.02F, 0.5F), c.blue_light);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.25F, -0.52F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.25F, -0.52F),
           QVector3D(0.72F, 0.02F, 0.02F), c.blue_accent);
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.25F, 0.52F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.25F, 0.52F),
           QVector3D(0.72F, 0.02F, 0.02F), c.blue_accent);
 
-  drawCyl(out, p.model, QVector3D(0.0F, 0.25F, 0.0F),
+  draw_cyl(out, p.model, QVector3D(0.0F, 0.25F, 0.0F),
           QVector3D(0.0F, 0.55F, 0.0F), 0.06F, c.marble, white);
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.58F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.58F, 0.0F),
           QVector3D(0.08F, 0.03F, 0.08F), c.blue_accent);
 }
 
-void drawChamber(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_chamber(const DrawContext &p, ISubmitter &out, Mesh *unit,
                  Texture *white, const CarthagePalette &c) {
   float const wall_h = 1.4F;
 
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(0.0F, wall_h * 0.5F + 0.2F, -1.2F),
           QVector3D(1.4F, wall_h * 0.5F, 0.1F), c.limestone);
 
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(-1.5F, wall_h * 0.5F + 0.2F, -0.5F),
           QVector3D(0.1F, wall_h * 0.5F, 0.6F), c.limestone);
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(1.5F, wall_h * 0.5F + 0.2F, -0.5F),
           QVector3D(0.1F, wall_h * 0.5F, 0.6F), c.limestone);
 
-  drawBox(out, unit, white, p.model, QVector3D(-0.6F, 0.65F, -1.15F),
+  draw_box(out, unit, white, p.model, QVector3D(-0.6F, 0.65F, -1.15F),
           QVector3D(0.25F, 0.35F, 0.03F), c.cedar_dark);
-  drawBox(out, unit, white, p.model, QVector3D(-0.6F, 0.98F, -1.15F),
+  draw_box(out, unit, white, p.model, QVector3D(-0.6F, 0.98F, -1.15F),
           QVector3D(0.25F, 0.05F, 0.03F), c.blue_accent);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.6F, 0.65F, -1.15F),
+  draw_box(out, unit, white, p.model, QVector3D(0.6F, 0.65F, -1.15F),
           QVector3D(0.25F, 0.35F, 0.03F), c.cedar_dark);
-  drawBox(out, unit, white, p.model, QVector3D(0.6F, 0.98F, -1.15F),
+  draw_box(out, unit, white, p.model, QVector3D(0.6F, 0.98F, -1.15F),
           QVector3D(0.25F, 0.05F, 0.03F), c.blue_accent);
 }
 
-void drawTerrace(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_terrace(const DrawContext &p, ISubmitter &out, Mesh *unit,
                  Texture *white, const CarthagePalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 2.05F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 2.05F, 0.0F),
           QVector3D(1.7F, 0.08F, 1.5F), c.marble);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 2.12F, 1.45F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 2.12F, 1.45F),
           QVector3D(1.65F, 0.05F, 0.05F), c.gold);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 2.18F, -0.2F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 2.18F, -0.2F),
           QVector3D(1.5F, 0.04F, 1.0F), c.terracotta);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 2.28F, -0.65F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 2.28F, -0.65F),
           QVector3D(1.45F, 0.06F, 0.05F), c.limestone);
 
   for (float x : {-1.4F, 1.4F}) {
-    drawBox(out, unit, white, p.model, QVector3D(x, 2.35F, -0.65F),
+    draw_box(out, unit, white, p.model, QVector3D(x, 2.35F, -0.65F),
             QVector3D(0.08F, 0.08F, 0.08F), c.gold);
   }
 }
 
-void drawTradingGoods(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_trading_goods(const DrawContext &p, ISubmitter &out, Mesh *unit,
                       Texture *white, const CarthagePalette &c) {
 
-  drawCyl(out, p.model, QVector3D(-1.2F, 0.2F, 1.1F),
+  draw_cyl(out, p.model, QVector3D(-1.2F, 0.2F, 1.1F),
           QVector3D(-1.2F, 0.5F, 1.1F), 0.08F, c.terracotta_dark, white);
-  drawCyl(out, p.model, QVector3D(-0.9F, 0.2F, 1.15F),
+  draw_cyl(out, p.model, QVector3D(-0.9F, 0.2F, 1.15F),
           QVector3D(-0.9F, 0.45F, 1.15F), 0.07F, c.terracotta, white);
 
-  drawCyl(out, p.model, QVector3D(1.1F, 0.2F, -0.9F),
+  draw_cyl(out, p.model, QVector3D(1.1F, 0.2F, -0.9F),
           QVector3D(1.1F, 0.42F, -0.9F), 0.06F, c.blue_accent, white);
 }
 
-void drawPhoenicianBanner(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_phoenician_banner(const DrawContext &p, ISubmitter &out, Mesh *unit,
                           Texture *white, const CarthagePalette &c) {
   float const pole_x = 0.0F;
   float const pole_z = -2.0F;
@@ -231,7 +231,7 @@ void drawPhoenicianBanner(const DrawContext &p, ISubmitter &out, Mesh *unit,
   float const beam_length = banner_width * 0.45F;
   float const max_lowering = pole_height * 0.85F;
 
-  auto captureColors = BarracksFlagRenderer::getCaptureColors(
+  auto captureColors = BarracksFlagRenderer::get_capture_colors(
       p, c.team, c.team_trim, max_lowering);
 
   float beam_y =
@@ -273,22 +273,22 @@ void drawPhoenicianBanner(const DrawContext &p, ISubmitter &out, Mesh *unit,
   trimTop.scale(QVector3D(banner_width / 2.0F + 0.02F, 0.04F, 0.015F));
   out.mesh(unit, trimTop, captureColors.teamTrimColor, white, 1.0F);
 
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(pole_x + 0.2F, pole_height + 0.12F, pole_z + 0.03F),
           QVector3D(0.26F, 0.02F, 0.01F), c.gold);
 }
 
-void drawRallyFlag(const DrawContext &p, ISubmitter &out, Texture *white,
+void draw_rally_flag(const DrawContext &p, ISubmitter &out, Texture *white,
                    const CarthagePalette &c) {
   BarracksFlagRenderer::FlagColors colors{.team = c.team,
                                           .teamTrim = c.team_trim,
                                           .timber = c.cedar,
                                           .timberLight = c.limestone,
                                           .woodDark = c.cedar_dark};
-  BarracksFlagRenderer::drawRallyFlagIfAny(p, out, white, colors);
+  BarracksFlagRenderer::draw_rally_flag_if_any(p, out, white, colors);
 }
 
-void drawHealthBar(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_health_bar(const DrawContext &p, ISubmitter &out, Mesh *unit,
                    Texture *white) {
   if (p.entity == nullptr)
     return;
@@ -302,17 +302,17 @@ void drawHealthBar(const DrawContext &p, ISubmitter &out, Mesh *unit,
     return;
 
   QVector3D const bg(0.06F, 0.06F, 0.06F);
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 2.65F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 2.65F, 0.0F),
           QVector3D(0.9F, 0.04F, 0.06F), bg);
 
   QVector3D const fg = QVector3D(0.22F, 0.78F, 0.22F) * ratio +
                        QVector3D(0.85F, 0.15F, 0.15F) * (1.0F - ratio);
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(-(0.9F * (1.0F - ratio)) * 0.5F, 2.66F, 0.0F),
           QVector3D(0.9F * ratio * 0.5F, 0.035F, 0.055F), fg);
 }
 
-void drawSelection(const DrawContext &p, ISubmitter &out) {
+void draw_selection(const DrawContext &p, ISubmitter &out) {
   QMatrix4x4 m;
   QVector3D const pos = p.model.column(3).toVector3D();
   m.translate(pos.x(), 0.0F, pos.z());
@@ -324,7 +324,7 @@ void drawSelection(const DrawContext &p, ISubmitter &out) {
   }
 }
 
-void drawBarracks(const DrawContext &p, ISubmitter &out) {
+void draw_barracks(const DrawContext &p, ISubmitter &out) {
   if (!p.resources || !p.entity)
     return;
 
@@ -336,24 +336,24 @@ void drawBarracks(const DrawContext &p, ISubmitter &out) {
   Mesh *unit = p.resources->unit();
   Texture *white = p.resources->white();
   QVector3D const team(r->color[0], r->color[1], r->color[2]);
-  CarthagePalette const c = makePalette(team);
-
-  drawPlatform(p, out, unit, white, c);
-  drawColonnade(p, out, unit, white, c);
-  drawCentralCourtyard(p, out, unit, white, c);
-  drawChamber(p, out, unit, white, c);
-  drawTerrace(p, out, unit, white, c);
-  drawTradingGoods(p, out, unit, white, c);
-  drawPhoenicianBanner(p, out, unit, white, c);
-  drawRallyFlag(p, out, white, c);
-  drawHealthBar(p, out, unit, white);
-  drawSelection(p, out);
+  CarthagePalette const c = make_palette(team);
+
+  draw_platform(p, out, unit, white, c);
+  draw_colonnade(p, out, unit, white, c);
+  draw_central_courtyard(p, out, unit, white, c);
+  draw_chamber(p, out, unit, white, c);
+  draw_terrace(p, out, unit, white, c);
+  draw_trading_goods(p, out, unit, white, c);
+  draw_phoenician_banner(p, out, unit, white, c);
+  draw_rally_flag(p, out, white, c);
+  draw_health_bar(p, out, unit, white);
+  draw_selection(p, out);
 }
 
 } // namespace
 
-void registerBarracksRenderer(Render::GL::EntityRendererRegistry &registry) {
-  registry.registerRenderer("barracks_carthage", drawBarracks);
+void register_barracks_renderer(Render::GL::EntityRendererRegistry &registry) {
+  registry.register_renderer("barracks_carthage", draw_barracks);
 }
 
 } // namespace Render::GL::Carthage

+ 1 - 1
render/entity/nations/carthage/barracks_renderer.h

@@ -4,6 +4,6 @@
 
 namespace Render::GL::Carthage {
 
-void registerBarracksRenderer(EntityRendererRegistry &registry);
+void register_barracks_renderer(EntityRendererRegistry &registry);
 
 }

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

@@ -53,7 +53,7 @@ struct MountedKnightExtras {
 
 class MountedKnightRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.40F, 1.05F, 1.10F};
   }
 
@@ -62,7 +62,7 @@ private:
   HorseRenderer m_horseRenderer;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -82,7 +82,7 @@ public:
     return QStringLiteral("horse_swordsman");
   }
 
-  void customizePose(const DrawContext &ctx,
+  void customize_pose(const DrawContext &ctx,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -297,7 +297,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -308,7 +308,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -340,7 +340,7 @@ private:
 void registerMountedKnightRenderer(
     Render::GL::EntityRendererRegistry &registry) {
   static MountedKnightRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/carthage/horse_swordsman",
       [](const DrawContext &ctx, ISubmitter &out) {
         static MountedKnightRenderer const static_renderer;

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

@@ -85,7 +85,7 @@ struct SpearmanExtras {
 
 class SpearmanRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.10F, 1.02F, 1.05F};
   }
 
@@ -93,7 +93,7 @@ private:
   mutable std::unordered_map<uint32_t, SpearmanExtras> m_extrasCache;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -101,7 +101,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -197,7 +197,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -208,7 +208,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -311,7 +311,7 @@ private:
 void registerSpearmanRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_spearman_styles_registered();
   static SpearmanRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/carthage/spearman", [](const DrawContext &ctx, ISubmitter &out) {
         static SpearmanRenderer const static_renderer;
         Shader *spearman_shader = nullptr;

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

@@ -97,7 +97,7 @@ struct KnightExtras {
 
 class KnightRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.40F, 1.05F, 1.10F};
   }
 
@@ -105,7 +105,7 @@ private:
   mutable std::unordered_map<uint32_t, KnightExtras> m_extrasCache;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -113,7 +113,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -211,7 +211,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -222,7 +222,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -380,7 +380,7 @@ private:
 void registerKnightRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_swordsman_styles_registered();
   static KnightRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/carthage/swordsman", [](const DrawContext &ctx, ISubmitter &out) {
         static KnightRenderer const static_renderer;
         Shader *swordsman_shader = nullptr;
@@ -400,7 +400,7 @@ void registerKnightRenderer(Render::GL::EntityRendererRegistry &registry) {
           scene_renderer->setCurrentShader(nullptr);
         }
       });
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/carthage/swordsman", [](const DrawContext &ctx, ISubmitter &out) {
         static KnightRenderer const static_renderer;
         Shader *swordsman_shader = nullptr;

+ 6 - 6
render/entity/nations/kingdom/archer_renderer.cpp

@@ -80,12 +80,12 @@ using Render::GL::Humanoid::saturate_color;
 
 class ArcherRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
 
     return {0.94F, 1.01F, 0.96F};
   }
 
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -93,7 +93,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -214,7 +214,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -225,7 +225,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     if (resolve_style(ctx).show_armor) {
@@ -294,7 +294,7 @@ private:
 void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_archer_styles_registered();
   static ArcherRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/kingdom/archer", [](const DrawContext &ctx, ISubmitter &out) {
         static ArcherRenderer const static_renderer;
         Shader *archer_shader = nullptr;

+ 38 - 38
render/entity/nations/kingdom/barracks_renderer.cpp

@@ -70,7 +70,7 @@ struct BarracksPalette {
   QVector3D teamTrim{0.48F, 0.54F, 0.60F};
 };
 
-inline auto makePalette(const QVector3D &team) -> BarracksPalette {
+inline auto make_palette(const QVector3D &team) -> BarracksPalette {
   BarracksPalette p;
   p.team = clampVec01(team);
   p.teamTrim =
@@ -78,7 +78,7 @@ inline auto makePalette(const QVector3D &team) -> BarracksPalette {
   return p;
 }
 
-inline void drawCylinder(ISubmitter &out, const QMatrix4x4 &model,
+inline void draw_cylinder(ISubmitter &out, const QMatrix4x4 &model,
                          const QVector3D &a, const QVector3D &b, float radius,
                          const QVector3D &color, Texture *white) {
   out.mesh(getUnitCylinder(), model * cylinderBetween(a, b, radius), color,
@@ -152,11 +152,11 @@ inline void drawWalls(const DrawContext &p, ISubmitter &out, Mesh *,
   const float y0 = r;
 
   auto log_x = [&](float y, float z, float x0, float x1, const QVector3D &col) {
-    drawCylinder(out, p.model, QVector3D(x0 - notch, y, z),
+    draw_cylinder(out, p.model, QVector3D(x0 - notch, y, z),
                  QVector3D(x1 + notch, y, z), r, col, white);
   };
   auto log_z = [&](float y, float x, float z0, float z1, const QVector3D &col) {
-    drawCylinder(out, p.model, QVector3D(x, y, z0 - notch),
+    draw_cylinder(out, p.model, QVector3D(x, y, z0 - notch),
                  QVector3D(x, y, z1 + notch), r, col, white);
   };
 
@@ -181,31 +181,31 @@ inline void drawWalls(const DrawContext &p, ISubmitter &out, Mesh *,
   }
 
   QVector3D const post_col = C.woodDark;
-  drawCylinder(out, p.model, QVector3D(-gap_half, y0, front_z),
+  draw_cylinder(out, p.model, QVector3D(-gap_half, y0, front_z),
                QVector3D(-gap_half, y0 + door_h, front_z), r * 0.95F, post_col,
                white);
-  drawCylinder(out, p.model, QVector3D(+gap_half, y0, front_z),
+  draw_cylinder(out, p.model, QVector3D(+gap_half, y0, front_z),
                QVector3D(+gap_half, y0 + door_h, front_z), r * 0.95F, post_col,
                white);
-  drawCylinder(out, p.model, QVector3D(-gap_half, y0 + door_h, front_z),
+  draw_cylinder(out, p.model, QVector3D(-gap_half, y0 + door_h, front_z),
                QVector3D(+gap_half, y0 + door_h, front_z), r, C.timberLight,
                white);
 
   float const brace_y0 = h * 0.35F;
   float const brace_y1 = h * 0.95F;
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(left_x + 0.08F, brace_y0, back_z + 0.10F),
                QVector3D(left_x + 0.38F, brace_y1, back_z + 0.10F), r * 0.6F,
                C.woodDark, white);
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(right_x - 0.08F, brace_y0, back_z + 0.10F),
                QVector3D(right_x - 0.38F, brace_y1, back_z + 0.10F), r * 0.6F,
                C.woodDark, white);
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(left_x + 0.08F, brace_y0, front_z - 0.10F),
                QVector3D(left_x + 0.38F, brace_y1, front_z - 0.10F), r * 0.6F,
                C.woodDark, white);
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(right_x - 0.08F, brace_y0, front_z - 0.10F),
                QVector3D(right_x - 0.38F, brace_y1, front_z - 0.10F), r * 0.6F,
                C.woodDark, white);
@@ -293,14 +293,14 @@ inline void drawRoofs(const DrawContext &p, ISubmitter &out, Mesh *,
   const float plate_y = h;
   const float ridge_y = h + rise;
 
-  drawCylinder(out, p.model, QVector3D(left_x - over, plate_y, front_z + over),
+  draw_cylinder(out, p.model, QVector3D(left_x - over, plate_y, front_z + over),
                QVector3D(right_x + over, plate_y, front_z + over), r,
                C.woodDark, white);
-  drawCylinder(out, p.model, QVector3D(left_x - over, plate_y, back_z - over),
+  draw_cylinder(out, p.model, QVector3D(left_x - over, plate_y, back_z - over),
                QVector3D(right_x + over, plate_y, back_z - over), r, C.woodDark,
                white);
 
-  drawCylinder(out, p.model, QVector3D(left_x - over * 0.5F, ridge_y, 0.0F),
+  draw_cylinder(out, p.model, QVector3D(left_x - over * 0.5F, ridge_y, 0.0F),
                QVector3D(right_x + over * 0.5F, ridge_y, 0.0F), r,
                C.timberLight, white);
 
@@ -310,10 +310,10 @@ inline void drawRoofs(const DrawContext &p, ISubmitter &out, Mesh *,
     float const x =
         (left_x - over * 0.5F) * (1.0F - t) + (right_x + over * 0.5F) * t;
 
-    drawCylinder(out, p.model, QVector3D(x, plate_y, back_z - over),
+    draw_cylinder(out, p.model, QVector3D(x, plate_y, back_z - over),
                  QVector3D(x, ridge_y, 0.0F), r * 0.85F, C.woodDark, white);
 
-    drawCylinder(out, p.model, QVector3D(x, plate_y, front_z + over),
+    draw_cylinder(out, p.model, QVector3D(x, plate_y, front_z + over),
                  QVector3D(x, ridge_y, 0.0F), r * 0.85F, C.woodDark, white);
   }
 
@@ -321,7 +321,7 @@ inline void drawRoofs(const DrawContext &p, ISubmitter &out, Mesh *,
     float const z = front ? (front_z + over - tz * (front_z + over))
                           : (back_z - over - tz * (back_z - over));
     float const y = plate_y + tz * (ridge_y - plate_y);
-    drawCylinder(out, p.model, QVector3D(left_x - over * 0.4F, y, z),
+    draw_cylinder(out, p.model, QVector3D(left_x - over * 0.4F, y, z),
                  QVector3D(right_x + over * 0.4F, y, z), r * 0.6F, C.timber,
                  white);
   };
@@ -333,9 +333,9 @@ inline void drawRoofs(const DrawContext &p, ISubmitter &out, Mesh *,
   auto split_thatch = [&](float y, float z, float rad, const QVector3D &col) {
     float const gap_l = ch.x - ch.gapRadius;
     float const gap_r = ch.x + ch.gapRadius;
-    drawCylinder(out, p.model, QVector3D(left_x - over * 0.35F, y, z),
+    draw_cylinder(out, p.model, QVector3D(left_x - over * 0.35F, y, z),
                  QVector3D(gap_l, y, z), rad, col, white);
-    drawCylinder(out, p.model, QVector3D(gap_r, y, z),
+    draw_cylinder(out, p.model, QVector3D(gap_r, y, z),
                  QVector3D(right_x + over * 0.35F, y, z), rad, col, white);
   };
 
@@ -390,12 +390,12 @@ inline void drawDoor(const DrawContext &p, ISubmitter &out, Mesh *unit,
             QVector3D(plank_w * 0.48F, d_h * 0.48F, 0.006F), plank_col);
   }
 
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(-d_w * 0.45F, y0 + d_h * 0.35F, zf + 0.03F),
                QVector3D(+d_w * 0.45F, y0 + d_h * 0.35F, zf + 0.03F), 0.02F,
                frame_col, white);
 
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(d_w * 0.32F, y0 + d_h * 0.45F, zf + 0.04F),
                QVector3D(d_w * 0.42F, y0 + d_h * 0.45F, zf + 0.04F), 0.012F,
                C.timberLight, white);
@@ -483,13 +483,13 @@ inline void drawAnnex(const DrawContext &p, ISubmitter &out, Mesh *unit,
   float const plate_y = annex_h;
   float const front_z = z + annex_d * 0.5F;
   float const back_z = z - annex_d * 0.5F;
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(x - annex_w * 0.52F, plate_y, back_z - 0.12F),
                QVector3D(x + annex_w * 0.52F, plate_y, back_z - 0.12F), 0.05F,
                C.woodDark, white);
 
   float const ridge_y = annex_h + BuildingProportions::annex_roof_height;
-  drawCylinder(out, p.model,
+  draw_cylinder(out, p.model,
                QVector3D(x - annex_w * 0.50F, ridge_y, back_z - 0.02F),
                QVector3D(x + annex_w * 0.50F, ridge_y, back_z - 0.02F), 0.05F,
                C.timberLight, white);
@@ -501,7 +501,7 @@ inline void drawAnnex(const DrawContext &p, ISubmitter &out, Mesh *unit,
     float const zrow = back_z - 0.02F - 0.10F * (1.0F - t);
     QVector3D const col =
         lerp(C.thatchDark, C.thatch, 0.5F + 0.4F * (1.0F - t));
-    drawCylinder(out, p.model, QVector3D(x - annex_w * 0.55F, y, zrow),
+    draw_cylinder(out, p.model, QVector3D(x - annex_w * 0.55F, y, zrow),
                  QVector3D(x + annex_w * 0.55F, y, zrow),
                  0.06F * (1.15F - 0.6F * t), col, white);
   }
@@ -553,7 +553,7 @@ inline void drawBannerAndPole(const DrawContext &p, ISubmitter &out, Mesh *unit,
   float const beam_length = target_width * 0.45F;
   float const max_lowering = pole_height * 0.85F;
 
-  auto captureColors = BarracksFlagRenderer::getCaptureColors(
+  auto captureColors = BarracksFlagRenderer::get_capture_colors(
       p, C.team, C.teamTrim, max_lowering);
 
   float beam_y =
@@ -563,12 +563,12 @@ inline void drawBannerAndPole(const DrawContext &p, ISubmitter &out, Mesh *unit,
 
   QVector3D const beam_start(pole_x + 0.02F, beam_y, pole_z);
   QVector3D const beam_end(pole_x + beam_length + 0.02F, beam_y, pole_z);
-  drawCylinder(out, p.model, beam_start, beam_end, pole_radius * 0.35F,
+  draw_cylinder(out, p.model, beam_start, beam_end, pole_radius * 0.35F,
                C.timber, white);
 
   QVector3D const connector_top(
       beam_end.x(), beam_end.y() - target_height * 0.35F, beam_end.z());
-  drawCylinder(out, p.model, beam_end, connector_top, pole_radius * 0.18F,
+  draw_cylinder(out, p.model, beam_end, connector_top, pole_radius * 0.18F,
                C.timberLight, white);
 
   float const panel_x = beam_end.x() + (target_width * 0.5F - beam_length);
@@ -588,17 +588,17 @@ inline void drawBannerAndPole(const DrawContext &p, ISubmitter &out, Mesh *unit,
       captureColors.teamTrimColor);
 }
 
-inline void drawRallyFlagIfAny(const DrawContext &p, ISubmitter &out,
+inline void draw_rally_flag_if_any(const DrawContext &p, ISubmitter &out,
                                Texture *white, const BarracksPalette &C) {
   BarracksFlagRenderer::FlagColors colors{.team = C.team,
                                           .teamTrim = C.teamTrim,
                                           .timber = C.timber,
                                           .timberLight = C.timberLight,
                                           .woodDark = C.woodDark};
-  BarracksFlagRenderer::drawRallyFlagIfAny(p, out, white, colors);
+  BarracksFlagRenderer::draw_rally_flag_if_any(p, out, white, colors);
 }
 
-inline void drawHealthBar(const DrawContext &p, ISubmitter &out, Mesh *unit,
+inline void draw_health_bar(const DrawContext &p, ISubmitter &out, Mesh *unit,
                           Texture *white) {
   if (p.entity == nullptr) {
     return;
@@ -641,7 +641,7 @@ inline void drawHealthBar(const DrawContext &p, ISubmitter &out, Mesh *unit,
           fg_color);
 }
 
-inline void drawSelectionFX(const DrawContext &p, ISubmitter &out) {
+inline void draw_selectionFX(const DrawContext &p, ISubmitter &out) {
   QMatrix4x4 m;
   QVector3D const pos = p.model.column(3).toVector3D();
   m.translate(pos.x(), 0.0F, pos.z());
@@ -653,7 +653,7 @@ inline void drawSelectionFX(const DrawContext &p, ISubmitter &out) {
   }
 }
 
-void drawBarracks(const DrawContext &p, ISubmitter &out) {
+void draw_barracks(const DrawContext &p, ISubmitter &out) {
   if ((p.resources == nullptr) || (p.entity == nullptr)) {
     return;
   }
@@ -668,7 +668,7 @@ void drawBarracks(const DrawContext &p, ISubmitter &out) {
   Texture *white = p.resources->white();
 
   QVector3D const team(r->color[0], r->color[1], r->color[2]);
-  BarracksPalette const c = makePalette(team);
+  BarracksPalette const c = make_palette(team);
 
   drawFoundation(p, out, unit, white, c);
   drawAnnex(p, out, unit, white, c);
@@ -680,15 +680,15 @@ void drawBarracks(const DrawContext &p, ISubmitter &out) {
   drawBannerAndPole(p, out, unit, white, c);
   drawProps(p, out, unit, white, c);
 
-  drawRallyFlagIfAny(p, out, white, c);
-  drawHealthBar(p, out, unit, white);
-  drawSelectionFX(p, out);
+  draw_rally_flag_if_any(p, out, white, c);
+  draw_health_bar(p, out, unit, white);
+  draw_selectionFX(p, out);
 }
 
 } // namespace
 
-void registerBarracksRenderer(Render::GL::EntityRendererRegistry &registry) {
-  registry.registerRenderer("barracks_kingdom", drawBarracks);
+void register_barracks_renderer(Render::GL::EntityRendererRegistry &registry) {
+  registry.register_renderer("barracks_kingdom", draw_barracks);
 }
 
 } // namespace Render::GL::Kingdom

+ 1 - 1
render/entity/nations/kingdom/barracks_renderer.h

@@ -4,6 +4,6 @@
 
 namespace Render::GL::Kingdom {
 
-void registerBarracksRenderer(EntityRendererRegistry &registry);
+void register_barracks_renderer(EntityRendererRegistry &registry);
 
 }

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

@@ -54,7 +54,7 @@ struct MountedKnightExtras {
 
 class MountedKnightRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.40F, 1.05F, 1.10F};
   }
 
@@ -63,7 +63,7 @@ private:
   HorseRenderer m_horseRenderer;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -83,7 +83,7 @@ public:
     return QStringLiteral("horse_swordsman");
   }
 
-  void customizePose(const DrawContext &ctx,
+  void customize_pose(const DrawContext &ctx,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -298,7 +298,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -309,7 +309,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -342,7 +342,7 @@ private:
 void registerMountedKnightRenderer(
     Render::GL::EntityRendererRegistry &registry) {
   static MountedKnightRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/kingdom/horse_swordsman",
       [](const DrawContext &ctx, ISubmitter &out) {
         static MountedKnightRenderer const static_renderer;

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

@@ -85,7 +85,7 @@ struct SpearmanExtras {
 
 class SpearmanRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.10F, 1.02F, 1.05F};
   }
 
@@ -93,7 +93,7 @@ private:
   mutable std::unordered_map<uint32_t, SpearmanExtras> m_extrasCache;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -101,7 +101,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -197,7 +197,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -208,7 +208,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -311,7 +311,7 @@ private:
 void registerSpearmanRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_spearman_styles_registered();
   static SpearmanRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/kingdom/spearman", [](const DrawContext &ctx, ISubmitter &out) {
         static SpearmanRenderer const static_renderer;
         Shader *spearman_shader = nullptr;

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

@@ -97,7 +97,7 @@ struct KnightExtras {
 
 class KnightRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.40F, 1.05F, 1.10F};
   }
 
@@ -105,7 +105,7 @@ private:
   mutable std::unordered_map<uint32_t, KnightExtras> m_extrasCache;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -113,7 +113,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -211,7 +211,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -222,7 +222,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -380,7 +380,7 @@ private:
 void registerKnightRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_swordsman_styles_registered();
   static KnightRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/kingdom/swordsman", [](const DrawContext &ctx, ISubmitter &out) {
         static KnightRenderer const static_renderer;
         Shader *swordsman_shader = nullptr;
@@ -400,7 +400,7 @@ void registerKnightRenderer(Render::GL::EntityRendererRegistry &registry) {
           scene_renderer->setCurrentShader(nullptr);
         }
       });
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/kingdom/swordsman", [](const DrawContext &ctx, ISubmitter &out) {
         static KnightRenderer const static_renderer;
         Shader *swordsman_shader = nullptr;

+ 6 - 6
render/entity/nations/roman/archer_renderer.cpp

@@ -80,12 +80,12 @@ using Render::GL::Humanoid::saturate_color;
 
 class ArcherRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
 
     return {0.94F, 1.01F, 0.96F};
   }
 
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -93,7 +93,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -214,7 +214,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
     using HP = HumanProportions;
 
@@ -239,7 +239,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     if (resolve_style(ctx).show_armor) {
@@ -307,7 +307,7 @@ private:
 void registerArcherRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_archer_styles_registered();
   static ArcherRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/roman/archer", [](const DrawContext &ctx, ISubmitter &out) {
         static ArcherRenderer const static_renderer;
         Shader *archer_shader = nullptr;

+ 38 - 38
render/entity/nations/roman/barracks_renderer.cpp

@@ -36,7 +36,7 @@ struct RomanPalette {
   QVector3D team_trim{0.48F, 0.54F, 0.60F};
 };
 
-inline auto makePalette(const QVector3D &team) -> RomanPalette {
+inline auto make_palette(const QVector3D &team) -> RomanPalette {
   RomanPalette p;
   p.team = clampVec01(team);
   p.team_trim =
@@ -44,7 +44,7 @@ inline auto makePalette(const QVector3D &team) -> RomanPalette {
   return p;
 }
 
-inline void drawBox(ISubmitter &out, Mesh *unit, Texture *white,
+inline void draw_box(ISubmitter &out, Mesh *unit, Texture *white,
                     const QMatrix4x4 &model, const QVector3D &pos,
                     const QVector3D &size, const QVector3D &color) {
   QMatrix4x4 m = model;
@@ -53,7 +53,7 @@ inline void drawBox(ISubmitter &out, Mesh *unit, Texture *white,
   out.mesh(unit, m, color, white, 1.0F);
 }
 
-inline void drawCyl(ISubmitter &out, const QMatrix4x4 &model,
+inline void draw_cyl(ISubmitter &out, const QMatrix4x4 &model,
                     const QVector3D &a, const QVector3D &b, float r,
                     const QVector3D &color, Texture *white) {
   out.mesh(getUnitCylinder(), model * cylinderBetween(a, b, r), color, white,
@@ -63,19 +63,19 @@ inline void drawCyl(ISubmitter &out, const QMatrix4x4 &model,
 void drawFortressBase(const DrawContext &p, ISubmitter &out, Mesh *unit,
                       Texture *white, const RomanPalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.15F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.15F, 0.0F),
           QVector3D(1.8F, 0.15F, 1.5F), c.stone_base);
 
   for (float x = -1.6F; x <= 1.6F; x += 0.4F) {
-    drawBox(out, unit, white, p.model, QVector3D(x, 0.35F, -1.4F),
+    draw_box(out, unit, white, p.model, QVector3D(x, 0.35F, -1.4F),
             QVector3D(0.18F, 0.08F, 0.08F), c.stone_dark);
-    drawBox(out, unit, white, p.model, QVector3D(x, 0.35F, 1.4F),
+    draw_box(out, unit, white, p.model, QVector3D(x, 0.35F, 1.4F),
             QVector3D(0.18F, 0.08F, 0.08F), c.stone_dark);
   }
   for (float z = -1.3F; z <= 1.3F; z += 0.4F) {
-    drawBox(out, unit, white, p.model, QVector3D(-1.7F, 0.35F, z),
+    draw_box(out, unit, white, p.model, QVector3D(-1.7F, 0.35F, z),
             QVector3D(0.08F, 0.08F, 0.18F), c.stone_dark);
-    drawBox(out, unit, white, p.model, QVector3D(1.7F, 0.35F, z),
+    draw_box(out, unit, white, p.model, QVector3D(1.7F, 0.35F, z),
             QVector3D(0.08F, 0.08F, 0.18F), c.stone_dark);
   }
 }
@@ -84,22 +84,22 @@ void drawFortressWalls(const DrawContext &p, ISubmitter &out, Mesh *unit,
                        Texture *white, const RomanPalette &c) {
   float const wall_height = 1.2F;
 
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(0.0F, wall_height * 0.5F + 0.3F, -1.3F),
           QVector3D(1.5F, wall_height * 0.5F, 0.12F), c.stone_light);
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(0.0F, wall_height * 0.5F + 0.3F, 1.3F),
           QVector3D(1.5F, wall_height * 0.5F, 0.12F), c.stone_light);
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(-1.6F, wall_height * 0.5F + 0.3F, 0.0F),
           QVector3D(0.12F, wall_height * 0.5F, 1.2F), c.stone_light);
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(1.6F, wall_height * 0.5F + 0.3F, 0.0F),
           QVector3D(0.12F, wall_height * 0.5F, 1.2F), c.stone_light);
 
   for (int i = 0; i < 6; ++i) {
     float const x = -1.2F + float(i) * 0.5F;
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(x, wall_height + 0.35F, -1.25F),
             QVector3D(0.2F, 0.05F, 0.05F), c.brick);
   }
@@ -113,11 +113,11 @@ void drawCornerTowers(const DrawContext &p, ISubmitter &out, Mesh *unit,
 
   for (int i = 0; i < 4; ++i) {
 
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(corners[i].x(), 0.65F, corners[i].z()),
             QVector3D(0.25F, 0.65F, 0.25F), c.stone_dark);
 
-    drawBox(out, unit, white, p.model,
+    draw_box(out, unit, white, p.model,
             QVector3D(corners[i].x(), 1.45F, corners[i].z()),
             QVector3D(0.28F, 0.15F, 0.28F), c.brick_dark);
 
@@ -125,7 +125,7 @@ void drawCornerTowers(const DrawContext &p, ISubmitter &out, Mesh *unit,
       float angle = float(j) * 1.57F;
       float ox = sinf(angle) * 0.18F;
       float oz = cosf(angle) * 0.18F;
-      drawBox(out, unit, white, p.model,
+      draw_box(out, unit, white, p.model,
               QVector3D(corners[i].x() + ox, 1.68F, corners[i].z() + oz),
               QVector3D(0.06F, 0.08F, 0.06F), c.stone_light);
     }
@@ -135,24 +135,24 @@ void drawCornerTowers(const DrawContext &p, ISubmitter &out, Mesh *unit,
 void drawCourtyard(const DrawContext &p, ISubmitter &out, Mesh *unit,
                    Texture *white, const RomanPalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.32F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.32F, 0.0F),
           QVector3D(1.2F, 0.02F, 0.9F), c.stone_base);
 
-  drawCyl(out, p.model, QVector3D(0.0F, 0.3F, 0.0F),
+  draw_cyl(out, p.model, QVector3D(0.0F, 0.3F, 0.0F),
           QVector3D(0.0F, 0.95F, 0.0F), 0.08F, c.stone_light, white);
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.65F, -0.85F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.65F, -0.85F),
           QVector3D(0.35F, 0.35F, 0.08F), c.brick);
 }
 
 void drawRomanRoof(const DrawContext &p, ISubmitter &out, Mesh *unit,
                    Texture *white, const RomanPalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 1.58F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 1.58F, 0.0F),
           QVector3D(1.55F, 0.05F, 1.25F), c.tile_red);
 
   for (float z = -1.0F; z <= 1.0F; z += 0.3F) {
-    drawBox(out, unit, white, p.model, QVector3D(0.0F, 1.62F, z),
+    draw_box(out, unit, white, p.model, QVector3D(0.0F, 1.62F, z),
             QVector3D(1.5F, 0.02F, 0.08F), c.tile_dark);
   }
 }
@@ -160,12 +160,12 @@ void drawRomanRoof(const DrawContext &p, ISubmitter &out, Mesh *unit,
 void drawGate(const DrawContext &p, ISubmitter &out, Mesh *unit, Texture *white,
               const RomanPalette &c) {
 
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 0.6F, 1.35F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 0.6F, 1.35F),
           QVector3D(0.5F, 0.6F, 0.08F), c.wood_dark);
 
   for (int i = 0; i < 3; ++i) {
     float y = 0.3F + float(i) * 0.3F;
-    drawBox(out, unit, white, p.model, QVector3D(0.0F, y, 1.37F),
+    draw_box(out, unit, white, p.model, QVector3D(0.0F, y, 1.37F),
             QVector3D(0.45F, 0.03F, 0.02F), c.iron);
   }
 }
@@ -192,7 +192,7 @@ void drawStandards(const DrawContext &p, ISubmitter &out, Mesh *unit,
   float const beam_length = banner_width * 0.45F;
   float const max_lowering = pole_height * 0.85F;
 
-  auto captureColors = BarracksFlagRenderer::getCaptureColors(
+  auto captureColors = BarracksFlagRenderer::get_capture_colors(
       p, c.team, c.team_trim, max_lowering);
 
   float beam_y =
@@ -234,22 +234,22 @@ void drawStandards(const DrawContext &p, ISubmitter &out, Mesh *unit,
   trimTop.scale(QVector3D(banner_width / 2.0F + 0.02F, 0.04F, 0.015F));
   out.mesh(unit, trimTop, captureColors.teamTrimColor, white, 1.0F);
 
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(pole_x, pole_height + 0.15F, pole_z),
           QVector3D(0.08F, 0.06F, 0.08F), c.iron);
 }
 
-void drawRallyFlag(const DrawContext &p, ISubmitter &out, Texture *white,
+void draw_rally_flag(const DrawContext &p, ISubmitter &out, Texture *white,
                    const RomanPalette &c) {
   BarracksFlagRenderer::FlagColors colors{.team = c.team,
                                           .teamTrim = c.team_trim,
                                           .timber = c.wood,
                                           .timberLight = c.stone_light,
                                           .woodDark = c.wood_dark};
-  BarracksFlagRenderer::drawRallyFlagIfAny(p, out, white, colors);
+  BarracksFlagRenderer::draw_rally_flag_if_any(p, out, white, colors);
 }
 
-void drawHealthBar(const DrawContext &p, ISubmitter &out, Mesh *unit,
+void draw_health_bar(const DrawContext &p, ISubmitter &out, Mesh *unit,
                    Texture *white) {
   if (p.entity == nullptr)
     return;
@@ -263,17 +263,17 @@ void drawHealthBar(const DrawContext &p, ISubmitter &out, Mesh *unit,
     return;
 
   QVector3D const bg(0.06F, 0.06F, 0.06F);
-  drawBox(out, unit, white, p.model, QVector3D(0.0F, 2.35F, 0.0F),
+  draw_box(out, unit, white, p.model, QVector3D(0.0F, 2.35F, 0.0F),
           QVector3D(0.9F, 0.04F, 0.06F), bg);
 
   QVector3D const fg = QVector3D(0.22F, 0.78F, 0.22F) * ratio +
                        QVector3D(0.85F, 0.15F, 0.15F) * (1.0F - ratio);
-  drawBox(out, unit, white, p.model,
+  draw_box(out, unit, white, p.model,
           QVector3D(-(0.9F * (1.0F - ratio)) * 0.5F, 2.36F, 0.0F),
           QVector3D(0.9F * ratio * 0.5F, 0.035F, 0.055F), fg);
 }
 
-void drawSelection(const DrawContext &p, ISubmitter &out) {
+void draw_selection(const DrawContext &p, ISubmitter &out) {
   QMatrix4x4 m;
   QVector3D const pos = p.model.column(3).toVector3D();
   m.translate(pos.x(), 0.0F, pos.z());
@@ -285,7 +285,7 @@ void drawSelection(const DrawContext &p, ISubmitter &out) {
   }
 }
 
-void drawBarracks(const DrawContext &p, ISubmitter &out) {
+void draw_barracks(const DrawContext &p, ISubmitter &out) {
   if (!p.resources || !p.entity)
     return;
 
@@ -297,7 +297,7 @@ void drawBarracks(const DrawContext &p, ISubmitter &out) {
   Mesh *unit = p.resources->unit();
   Texture *white = p.resources->white();
   QVector3D const team(r->color[0], r->color[1], r->color[2]);
-  RomanPalette const c = makePalette(team);
+  RomanPalette const c = make_palette(team);
 
   drawFortressBase(p, out, unit, white, c);
   drawFortressWalls(p, out, unit, white, c);
@@ -306,15 +306,15 @@ void drawBarracks(const DrawContext &p, ISubmitter &out) {
   drawRomanRoof(p, out, unit, white, c);
   drawGate(p, out, unit, white, c);
   drawStandards(p, out, unit, white, c);
-  drawRallyFlag(p, out, white, c);
-  drawHealthBar(p, out, unit, white);
-  drawSelection(p, out);
+  draw_rally_flag(p, out, white, c);
+  draw_health_bar(p, out, unit, white);
+  draw_selection(p, out);
 }
 
 } // namespace
 
-void registerBarracksRenderer(Render::GL::EntityRendererRegistry &registry) {
-  registry.registerRenderer("barracks_roman", drawBarracks);
+void register_barracks_renderer(Render::GL::EntityRendererRegistry &registry) {
+  registry.register_renderer("barracks_roman", draw_barracks);
 }
 
 } // namespace Render::GL::Roman

+ 1 - 1
render/entity/nations/roman/barracks_renderer.h

@@ -4,6 +4,6 @@
 
 namespace Render::GL::Roman {
 
-void registerBarracksRenderer(EntityRendererRegistry &registry);
+void register_barracks_renderer(EntityRendererRegistry &registry);
 
 }

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

@@ -53,7 +53,7 @@ struct MountedKnightExtras {
 
 class MountedKnightRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.40F, 1.05F, 1.10F};
   }
 
@@ -62,7 +62,7 @@ private:
   HorseRenderer m_horseRenderer;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -82,7 +82,7 @@ public:
     return QStringLiteral("horse_swordsman");
   }
 
-  void customizePose(const DrawContext &ctx,
+  void customize_pose(const DrawContext &ctx,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -297,7 +297,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -308,7 +308,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -340,7 +340,7 @@ private:
 void registerMountedKnightRenderer(
     Render::GL::EntityRendererRegistry &registry) {
   static MountedKnightRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/roman/horse_swordsman",
       [](const DrawContext &ctx, ISubmitter &out) {
         static MountedKnightRenderer const static_renderer;

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

@@ -85,7 +85,7 @@ struct SpearmanExtras {
 
 class SpearmanRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.10F, 1.02F, 1.05F};
   }
 
@@ -93,7 +93,7 @@ private:
   mutable std::unordered_map<uint32_t, SpearmanExtras> m_extrasCache;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -101,7 +101,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -197,7 +197,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -208,7 +208,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -311,7 +311,7 @@ private:
 void registerSpearmanRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_spearman_styles_registered();
   static SpearmanRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/roman/spearman", [](const DrawContext &ctx, ISubmitter &out) {
         static SpearmanRenderer const static_renderer;
         Shader *spearman_shader = nullptr;

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

@@ -97,7 +97,7 @@ struct KnightExtras {
 
 class KnightRenderer : public HumanoidRendererBase {
 public:
-  auto getProportionScaling() const -> QVector3D override {
+  auto get_proportion_scaling() const -> QVector3D override {
     return {1.40F, 1.05F, 1.10F};
   }
 
@@ -105,7 +105,7 @@ private:
   mutable std::unordered_map<uint32_t, KnightExtras> m_extrasCache;
 
 public:
-  void getVariant(const DrawContext &ctx, uint32_t seed,
+  void get_variant(const DrawContext &ctx, uint32_t seed,
                   HumanoidVariant &v) const override {
     QVector3D const team_tint = resolveTeamTint(ctx);
     v.palette = makeHumanoidPalette(team_tint, seed);
@@ -113,7 +113,7 @@ public:
     apply_palette_overrides(style, team_tint, v);
   }
 
-  void customizePose(const DrawContext &,
+  void customize_pose(const DrawContext &,
                      const HumanoidAnimationContext &anim_ctx, uint32_t seed,
                      HumanoidPose &pose) const override {
     using HP = HumanProportions;
@@ -211,7 +211,7 @@ public:
     }
   }
 
-  void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                   const HumanoidPose &pose, ISubmitter &out) const override {
 
     auto &registry = EquipmentRegistry::instance();
@@ -222,7 +222,7 @@ public:
     }
   }
 
-  void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                  const HumanoidPose &pose, const HumanoidAnimationContext &anim,
                  ISubmitter &out) const override {
     auto &registry = EquipmentRegistry::instance();
@@ -380,7 +380,7 @@ private:
 void registerKnightRenderer(Render::GL::EntityRendererRegistry &registry) {
   ensure_swordsman_styles_registered();
   static KnightRenderer const renderer;
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/roman/swordsman", [](const DrawContext &ctx, ISubmitter &out) {
         static KnightRenderer const static_renderer;
         Shader *swordsman_shader = nullptr;
@@ -400,7 +400,7 @@ void registerKnightRenderer(Render::GL::EntityRendererRegistry &registry) {
           scene_renderer->setCurrentShader(nullptr);
         }
       });
-  registry.registerRenderer(
+  registry.register_renderer(
       "troops/roman/swordsman", [](const DrawContext &ctx, ISubmitter &out) {
         static KnightRenderer const static_renderer;
         Shader *swordsman_shader = nullptr;

+ 2 - 2
render/entity/registry.cpp

@@ -18,7 +18,7 @@
 
 namespace Render::GL {
 
-void EntityRendererRegistry::registerRenderer(const std::string &type,
+void EntityRendererRegistry::register_renderer(const std::string &type,
                                               RenderFunc func) {
   m_map[type] = std::move(func);
 }
@@ -47,7 +47,7 @@ void registerBuiltInEntityRenderers(EntityRendererRegistry &registry) {
   Kingdom::registerMountedKnightRenderer(registry);
   Roman::registerMountedKnightRenderer(registry);
   Carthage::registerMountedKnightRenderer(registry);
-  registerBarracksRenderer(registry);
+  register_barracks_renderer(registry);
 }
 
 } // namespace Render::GL

+ 1 - 1
render/entity/registry.h

@@ -38,7 +38,7 @@ using RenderFunc = std::function<void(const DrawContext &, ISubmitter &out)>;
 
 class EntityRendererRegistry {
 public:
-  void registerRenderer(const std::string &type, RenderFunc func);
+  void register_renderer(const std::string &type, RenderFunc func);
   auto get(const std::string &type) const -> RenderFunc;
 
 private:

+ 252 - 0
render/equipment/armor/chainmail_armor.cpp

@@ -0,0 +1,252 @@
+#include "chainmail_armor.h"
+#include "../../geom/transforms.h"
+#include "../../gl/primitives.h"
+#include "../../humanoid/humanoid_math.h"
+#include "../../humanoid/rig.h"
+#include "../../submitter.h"
+#include <QMatrix4x4>
+#include <QVector3D>
+#include <cmath>
+#include <numbers>
+
+namespace Render::GL {
+
+using Render::Geom::cylinderBetween;
+
+auto ChainmailArmorRenderer::calculateRingColor(float x, float y,
+                                                 float z) const -> QVector3D {
+  // Procedural rust/weathering based on position
+  float rust_noise = std::sin(x * 127.3F) * std::cos(y * 97.1F) * 
+                     std::sin(z * 83.7F);
+  rust_noise = (rust_noise + 1.0F) * 0.5F; // Normalize to [0,1]
+  
+  // More rust in lower areas (gravity effect)
+  float gravity_rust = std::clamp(1.0F - y * 0.8F, 0.0F, 1.0F);
+  float total_rust = (rust_noise * 0.6F + gravity_rust * 0.4F) * m_config.rust_amount;
+  
+  return m_config.metal_color * (1.0F - total_rust) + 
+         m_config.rust_tint * total_rust;
+}
+
+void ChainmailArmorRenderer::render(const DrawContext &ctx,
+                                    const BodyFrames &frames,
+                                    const HumanoidPalette &palette,
+                                    const HumanoidAnimationContext &anim,
+                                    ISubmitter &submitter) {
+  (void)palette;
+  (void)anim;
+
+  renderTorsoMail(ctx, frames, submitter);
+  
+  if (m_config.has_shoulder_guards) {
+    renderShoulderGuards(ctx, frames, submitter);
+  }
+  
+  if (m_config.has_arm_coverage && m_config.coverage > 0.5F) {
+    renderArmMail(ctx, frames, submitter);
+  }
+}
+
+void ChainmailArmorRenderer::renderTorsoMail(const DrawContext &ctx,
+                                             const BodyFrames &frames,
+                                             ISubmitter &submitter) {
+  const AttachmentFrame &torso = frames.torso;
+  const AttachmentFrame &waist = frames.waist;
+  
+  if (torso.radius <= 0.0F) {
+    return;
+  }
+
+  float const torso_r = torso.radius;
+  float const coverage_height = m_config.coverage;
+  
+  // Main chainmail hauberk body - layered construction
+  int const vertical_segments = m_config.detail_level >= 2 ? 16 : 8;
+  
+  for (int seg = 0; seg < vertical_segments; ++seg) {
+    float t0 = static_cast<float>(seg) / static_cast<float>(vertical_segments);
+    float t1 = static_cast<float>(seg + 1) / static_cast<float>(vertical_segments);
+    
+    // Interpolate between torso and waist
+    QVector3D pos0 = torso.origin * (1.0F - t0) + waist.origin * t0;
+    QVector3D pos1 = torso.origin * (1.0F - t1) + waist.origin * t1;
+    
+    float r0 = torso_r * (1.0F + t0 * 0.15F); // Slight flare at waist
+    float r1 = torso_r * (1.0F + t1 * 0.15F);
+    
+    QVector3D ring_color = calculateRingColor(pos0.x(), pos0.y(), pos0.z());
+    
+    // If high detail, render actual ring structure
+    if (m_config.detail_level >= 2) {
+      renderRingDetails(ctx, pos0, r0, (pos1 - pos0).length(),
+                        torso.up, torso.right, submitter);
+    } else {
+      // Lower detail: solid segments with chainmail texture hint
+      submitter.mesh(getUnitCylinder(),
+                     cylinderBetween(ctx.model, pos0, pos1, (r0 + r1) * 0.5F * 1.02F),
+                     ring_color, nullptr, 0.75F);
+    }
+  }
+  
+  // Bottom edge rings (hanging mail at waist)
+  if (coverage_height > 0.7F) {
+    int const edge_rings = m_config.detail_level >= 1 ? 16 : 8;
+    
+    for (int i = 0; i < edge_rings; ++i) {
+      float angle = (static_cast<float>(i) / static_cast<float>(edge_rings)) *
+                    2.0F * std::numbers::pi_v<float>;
+      
+      float x = std::cos(angle);
+      float z = std::sin(angle);
+      
+      QVector3D ring_pos = waist.origin + 
+                           waist.right * (x * torso_r * 1.15F) +
+                           waist.forward * (z * torso_r * 1.15F) +
+                           waist.up * (-0.05F);
+      
+      QMatrix4x4 ring_m = ctx.model;
+      ring_m.translate(ring_pos);
+      ring_m.scale(m_config.ring_size * 1.5F);
+      
+      QVector3D edge_color = calculateRingColor(ring_pos.x(), ring_pos.y(), ring_pos.z());
+      submitter.mesh(getUnitSphere(), ring_m, edge_color, nullptr, 0.8F);
+    }
+  }
+}
+
+void ChainmailArmorRenderer::renderShoulderGuards(const DrawContext &ctx,
+                                                  const BodyFrames &frames,
+                                                  ISubmitter &submitter) {
+  const AttachmentFrame &shoulder_l = frames.shoulderL;
+  const AttachmentFrame &shoulder_r = frames.shoulderR;
+  const AttachmentFrame &torso = frames.torso;
+  
+  // Left shoulder pauldron
+  QVector3D left_base = shoulder_l.origin;
+  QVector3D left_tip = left_base + torso.up * 0.08F + torso.right * (-0.05F);
+  
+  float const shoulder_r = 0.08F;
+  
+  QVector3D left_color = calculateRingColor(left_base.x(), left_base.y(), left_base.z());
+  submitter.mesh(getUnitCylinder(),
+                 cylinderBetween(ctx.model, left_base, left_tip, shoulder_r),
+                 left_color, nullptr, 0.8F);
+  
+  // Right shoulder pauldron
+  QVector3D right_base = shoulder_r.origin;
+  QVector3D right_tip = right_base + torso.up * 0.08F + torso.right * 0.05F;
+  
+  QVector3D right_color = calculateRingColor(right_base.x(), right_base.y(), right_base.z());
+  submitter.mesh(getUnitCylinder(),
+                 cylinderBetween(ctx.model, right_base, right_tip, shoulder_r),
+                 right_color, nullptr, 0.8F);
+  
+  // Layered shoulder protection (multiple overlapping ring rows)
+  if (m_config.detail_level >= 1) {
+    for (int layer = 0; layer < 3; ++layer) {
+      float layer_offset = static_cast<float>(layer) * 0.025F;
+      
+      QVector3D left_layer = left_base + torso.up * (-layer_offset);
+      QVector3D right_layer = right_base + torso.up * (-layer_offset);
+      
+      QMatrix4x4 left_m = ctx.model;
+      left_m.translate(left_layer);
+      left_m.scale(shoulder_r * 1.3F);
+      submitter.mesh(getUnitSphere(), left_m,
+                     left_color * (1.0F - layer_offset), nullptr, 0.75F);
+      
+      QMatrix4x4 right_m = ctx.model;
+      right_m.translate(right_layer);
+      right_m.scale(shoulder_r * 1.3F);
+      submitter.mesh(getUnitSphere(), right_m,
+                     right_color * (1.0F - layer_offset), nullptr, 0.75F);
+    }
+  }
+}
+
+void ChainmailArmorRenderer::renderArmMail(const DrawContext &ctx,
+                                           const BodyFrames &frames,
+                                           ISubmitter &submitter) {
+  // Arm coverage (sleeves) extending from shoulders to elbows
+  const AttachmentFrame &shoulder_l = frames.shoulderL;
+  const AttachmentFrame &shoulder_r = frames.shoulderR;
+  const AttachmentFrame &hand_l = frames.handL;
+  const AttachmentFrame &hand_r = frames.handR;
+  
+  // Left arm mail sleeve
+  QVector3D left_shoulder = shoulder_l.origin;
+  QVector3D left_elbow = (left_shoulder + hand_l.origin) * 0.5F; // Approximate elbow
+  
+  int const arm_segments = m_config.detail_level >= 2 ? 6 : 3;
+  
+  for (int i = 0; i < arm_segments; ++i) {
+    float t0 = static_cast<float>(i) / static_cast<float>(arm_segments);
+    float t1 = static_cast<float>(i + 1) / static_cast<float>(arm_segments);
+    
+    QVector3D pos0 = left_shoulder * (1.0F - t0) + left_elbow * t0;
+    QVector3D pos1 = left_shoulder * (1.0F - t1) + left_elbow * t1;
+    
+    float radius = 0.05F * (1.0F - t0 * 0.2F); // Taper toward elbow
+    
+    QVector3D color = calculateRingColor(pos0.x(), pos0.y(), pos0.z());
+    submitter.mesh(getUnitCylinder(),
+                   cylinderBetween(ctx.model, pos0, pos1, radius),
+                   color, nullptr, 0.75F);
+  }
+  
+  // Right arm mail sleeve
+  QVector3D right_shoulder = shoulder_r.origin;
+  QVector3D right_elbow = (right_shoulder + hand_r.origin) * 0.5F;
+  
+  for (int i = 0; i < arm_segments; ++i) {
+    float t0 = static_cast<float>(i) / static_cast<float>(arm_segments);
+    float t1 = static_cast<float>(i + 1) / static_cast<float>(arm_segments);
+    
+    QVector3D pos0 = right_shoulder * (1.0F - t0) + right_elbow * t0;
+    QVector3D pos1 = right_shoulder * (1.0F - t1) + right_elbow * t1;
+    
+    float radius = 0.05F * (1.0F - t0 * 0.2F);
+    
+    QVector3D color = calculateRingColor(pos0.x(), pos0.y(), pos0.z());
+    submitter.mesh(getUnitCylinder(),
+                   cylinderBetween(ctx.model, pos0, pos1, radius),
+                   color, nullptr, 0.75F);
+  }
+}
+
+void ChainmailArmorRenderer::renderRingDetails(
+    const DrawContext &ctx, const QVector3D &center, float radius,
+    float height, const QVector3D &up, const QVector3D &right,
+    ISubmitter &submitter) {
+  // Render individual interlocking rings for high detail mode
+  int const rings_around = 24;
+  int const rings_vertical = 4;
+  
+  for (int row = 0; row < rings_vertical; ++row) {
+    float y = (static_cast<float>(row) / static_cast<float>(rings_vertical)) * height;
+    
+    // Offset alternating rows for interlocking pattern
+    float row_offset = (row % 2) * 0.5F;
+    
+    for (int col = 0; col < rings_around; ++col) {
+      float angle = ((static_cast<float>(col) + row_offset) / 
+                     static_cast<float>(rings_around)) * 
+                    2.0F * std::numbers::pi_v<float>;
+      
+      float x = std::cos(angle) * radius;
+      float z = std::sin(angle) * radius;
+      
+      QVector3D ring_pos = center + up * y + right * x + 
+                           QVector3D::crossProduct(up, right).normalized() * z;
+      
+      QMatrix4x4 ring_m = ctx.model;
+      ring_m.translate(ring_pos);
+      ring_m.scale(m_config.ring_size);
+      
+      QVector3D color = calculateRingColor(ring_pos.x(), ring_pos.y(), ring_pos.z());
+      submitter.mesh(getUnitSphere(), ring_m, color, nullptr, 0.85F);
+    }
+  }
+}
+
+} // namespace Render::GL

+ 48 - 0
render/equipment/armor/chainmail_armor.h

@@ -0,0 +1,48 @@
+#pragma once
+
+#include "../../humanoid/rig.h"
+#include "../../palette.h"
+#include "../i_equipment_renderer.h"
+#include <QVector3D>
+
+namespace Render::GL {
+
+struct ChainmailArmorConfig {
+  QVector3D metal_color = QVector3D(0.65F, 0.67F, 0.70F); // Steel gray
+  QVector3D rust_tint = QVector3D(0.52F, 0.35F, 0.25F);
+  float coverage = 1.0F; // 0.0 = minimal, 1.0 = full coverage
+  float rust_amount = 0.15F; // 0.0 = pristine, 1.0 = heavily rusted
+  float ring_size = 0.008F;
+  bool has_shoulder_guards = true;
+  bool has_arm_coverage = true;
+  int detail_level = 2; // 0=low (simple), 1=medium, 2=high (individual rings)
+};
+
+class ChainmailArmorRenderer : public IEquipmentRenderer {
+public:
+  ChainmailArmorRenderer() = default;
+
+  void setConfig(const ChainmailArmorConfig &config) { m_config = config; }
+
+  void render(const DrawContext &ctx, const BodyFrames &frames,
+              const HumanoidPalette &palette,
+              const HumanoidAnimationContext &anim,
+              ISubmitter &submitter) override;
+
+private:
+  ChainmailArmorConfig m_config;
+
+  void renderTorsoMail(const DrawContext &ctx, const BodyFrames &frames,
+                       ISubmitter &submitter);
+  void renderShoulderGuards(const DrawContext &ctx, const BodyFrames &frames,
+                            ISubmitter &submitter);
+  void renderArmMail(const DrawContext &ctx, const BodyFrames &frames,
+                     ISubmitter &submitter);
+  void renderRingDetails(const DrawContext &ctx, const QVector3D &center,
+                         float radius, float height, const QVector3D &up,
+                         const QVector3D &right, ISubmitter &submitter);
+  
+  auto calculateRingColor(float x, float y, float z) const -> QVector3D;
+};
+
+} // namespace Render::GL

+ 264 - 0
render/equipment/helmets/carthage_light_helmet.cpp

@@ -0,0 +1,264 @@
+#include "carthage_light_helmet.h"
+#include "../../geom/transforms.h"
+#include "../../gl/primitives.h"
+#include "../../humanoid/humanoid_math.h"
+#include "../../humanoid/rig.h"
+#include "../../submitter.h"
+#include <QMatrix4x4>
+#include <QQuaternion>
+#include <QVector3D>
+#include <cmath>
+#include <numbers>
+
+namespace Render::GL {
+
+using Render::Geom::cylinderBetween;
+using Render::Geom::sphereAt;
+
+void CarthageLightHelmetRenderer::render(
+    const DrawContext &ctx, const BodyFrames &frames,
+    const HumanoidPalette &palette, const HumanoidAnimationContext &anim,
+    ISubmitter &submitter) {
+  (void)anim;
+  (void)palette;
+
+  const AttachmentFrame &head = frames.head;
+  if (head.radius <= 0.0F) {
+    return;
+  }
+
+  renderBowl(ctx, head, submitter);
+  renderBrim(ctx, head, submitter);
+  renderCheekGuards(ctx, head, submitter);
+  
+  if (m_config.has_nasal_guard) {
+    renderNasalGuard(ctx, head, submitter);
+  }
+  
+  if (m_config.has_crest) {
+    renderCrest(ctx, head, submitter);
+  }
+  
+  if (m_config.detail_level >= 2) {
+    renderRivets(ctx, head, submitter);
+  }
+}
+
+void CarthageLightHelmetRenderer::renderBowl(const DrawContext &ctx,
+                                             const AttachmentFrame &head,
+                                             ISubmitter &submitter) {
+  // Main helmet bowl - hemispherical bronze cap
+  float const head_r = head.radius;
+  float const bowl_height = m_config.helmet_height;
+  
+  auto headPoint = [&](const QVector3D &normalized) -> QVector3D {
+    return HumanoidRendererBase::frameLocalPosition(head, normalized);
+  };
+
+  // Create graduated helmet bowl with multiple segments for realism
+  int const segments = m_config.detail_level >= 2 ? 16 : 8;
+  
+  for (int i = 0; i < segments; ++i) {
+    float t0 = static_cast<float>(i) / static_cast<float>(segments);
+    float t1 = static_cast<float>(i + 1) / static_cast<float>(segments);
+    
+    // Spherical cap profile
+    float angle0 = t0 * std::numbers::pi_v<float> * 0.5F;
+    float angle1 = t1 * std::numbers::pi_v<float> * 0.5F;
+    
+    float y0 = std::cos(angle0) * bowl_height;
+    float y1 = std::cos(angle1) * bowl_height;
+    float r0 = std::sin(angle0) * head_r * 1.08F;
+    float r1 = std::sin(angle1) * head_r * 1.08F;
+    
+    QVector3D bottom = headPoint(QVector3D(0.0F, 0.85F - t0 * 0.3F, 0.0F));
+    QVector3D top = headPoint(QVector3D(0.0F, 0.85F - t1 * 0.3F, 0.0F));
+    
+    // Vary bronze color slightly per segment for hammered metal look
+    float variation = 1.0F + (std::sin(static_cast<float>(i) * 1.7F) * 0.08F);
+    QVector3D segment_color = m_config.bronze_color * variation;
+    
+    submitter.mesh(getUnitCylinder(),
+                   cylinderBetween(ctx.model, bottom, top, (r0 + r1) * 0.5F),
+                   segment_color, nullptr, 0.85F);
+  }
+  
+  // Top dome cap
+  QVector3D apex = headPoint(QVector3D(0.0F, 1.0F, 0.0F));
+  QMatrix4x4 apex_m = ctx.model;
+  apex_m.translate(apex);
+  apex_m.scale(head_r * 0.25F);
+  submitter.mesh(getUnitSphere(), apex_m, 
+                 m_config.bronze_color * 1.15F, nullptr, 0.9F);
+}
+
+void CarthageLightHelmetRenderer::renderBrim(const DrawContext &ctx,
+                                             const AttachmentFrame &head,
+                                             ISubmitter &submitter) {
+  float const head_r = head.radius;
+  float const brim_width = m_config.brim_width;
+  
+  auto headPoint = [&](const QVector3D &normalized) -> QVector3D {
+    return HumanoidRendererBase::frameLocalPosition(head, normalized);
+  };
+
+  // Front brim protection
+  QVector3D brim_base = headPoint(QVector3D(0.0F, 0.35F, 0.65F));
+  QVector3D brim_tip = brim_base + head.forward * brim_width;
+  
+  QMatrix4x4 brim_m = ctx.model;
+  brim_m.translate((brim_base + brim_tip) * 0.5F);
+  
+  // Orient brim forward
+  QVector3D brim_vec = brim_tip - brim_base;
+  float brim_len = brim_vec.length();
+  if (brim_len > 0.001F) {
+    brim_vec.normalize();
+    QVector3D right = QVector3D::crossProduct(brim_vec, head.up).normalized();
+    QVector3D up = QVector3D::crossProduct(right, brim_vec);
+    
+    QMatrix4x4 rotation;
+    rotation.setColumn(0, QVector4D(right, 0.0F));
+    rotation.setColumn(1, QVector4D(up, 0.0F));
+    rotation.setColumn(2, QVector4D(brim_vec, 0.0F));
+    rotation.setColumn(3, QVector4D(0.0F, 0.0F, 0.0F, 1.0F));
+    
+    brim_m = brim_m * rotation;
+  }
+  
+  brim_m.scale(head_r * 1.1F, head_r * 0.15F, brim_len * 0.5F);
+  submitter.mesh(getUnitSphere(), brim_m, 
+                 m_config.bronze_color * 0.92F, nullptr, 0.85F);
+}
+
+void CarthageLightHelmetRenderer::renderCheekGuards(
+    const DrawContext &ctx, const AttachmentFrame &head,
+    ISubmitter &submitter) {
+  float const head_r = head.radius;
+  float const guard_len = m_config.cheek_guard_length;
+  
+  auto headPoint = [&](const QVector3D &normalized) -> QVector3D {
+    return HumanoidRendererBase::frameLocalPosition(head, normalized);
+  };
+
+  // Left cheek guard
+  QVector3D left_top = headPoint(QVector3D(-0.75F, 0.45F, 0.35F));
+  QVector3D left_bot = left_top + head.up * (-guard_len) + 
+                       head.forward * 0.02F;
+  
+  submitter.mesh(getUnitCylinder(),
+                 cylinderBetween(ctx.model, left_top, left_bot, head_r * 0.42F),
+                 m_config.bronze_color * 0.88F, nullptr, 0.8F);
+  
+  // Right cheek guard
+  QVector3D right_top = headPoint(QVector3D(0.75F, 0.45F, 0.35F));
+  QVector3D right_bot = right_top + head.up * (-guard_len) + 
+                        head.forward * 0.02F;
+  
+  submitter.mesh(getUnitCylinder(),
+                 cylinderBetween(ctx.model, right_top, right_bot, head_r * 0.42F),
+                 m_config.bronze_color * 0.88F, nullptr, 0.8F);
+  
+  // Cheek guard attachment rivets
+  if (m_config.detail_level >= 1) {
+    for (auto pos : {left_top, right_top}) {
+      QMatrix4x4 rivet_m = ctx.model;
+      rivet_m.translate(pos);
+      rivet_m.scale(head_r * 0.08F);
+      submitter.mesh(getUnitSphere(), rivet_m,
+                     m_config.bronze_color * 1.3F, nullptr, 1.0F);
+    }
+  }
+}
+
+void CarthageLightHelmetRenderer::renderNasalGuard(
+    const DrawContext &ctx, const AttachmentFrame &head,
+    ISubmitter &submitter) {
+  float const head_r = head.radius;
+  
+  auto headPoint = [&](const QVector3D &normalized) -> QVector3D {
+    return HumanoidRendererBase::frameLocalPosition(head, normalized);
+  };
+
+  // Vertical nose guard strip
+  QVector3D nasal_top = headPoint(QVector3D(0.0F, 0.55F, 0.85F));
+  QVector3D nasal_bot = headPoint(QVector3D(0.0F, 0.0F, 0.92F));
+  
+  submitter.mesh(getUnitCylinder(),
+                 cylinderBetween(ctx.model, nasal_bot, nasal_top, head_r * 0.12F),
+                 m_config.bronze_color * 0.95F, nullptr, 0.9F);
+}
+
+void CarthageLightHelmetRenderer::renderCrest(const DrawContext &ctx,
+                                              const AttachmentFrame &head,
+                                              ISubmitter &submitter) {
+  float const head_r = head.radius;
+  
+  auto headPoint = [&](const QVector3D &normalized) -> QVector3D {
+    return HumanoidRendererBase::frameLocalPosition(head, normalized);
+  };
+
+  // Horsehair crest plume (red/purple dyed)
+  QVector3D crest_color(0.65F, 0.15F, 0.18F); // Dark red
+  
+  // Crest base mount
+  QVector3D crest_base = headPoint(QVector3D(0.0F, 0.95F, -0.15F));
+  QMatrix4x4 base_m = ctx.model;
+  base_m.translate(crest_base);
+  base_m.scale(head_r * 0.18F, head_r * 0.08F, head_r * 0.3F);
+  submitter.mesh(getUnitSphere(), base_m,
+                 m_config.bronze_color * 1.1F, nullptr, 0.95F);
+  
+  // Horsehair plume strands (multiple cylinders)
+  int const hair_strands = m_config.detail_level >= 2 ? 7 : 4;
+  
+  for (int i = 0; i < hair_strands; ++i) {
+    float offset = (static_cast<float>(i) - static_cast<float>(hair_strands) * 0.5F) 
+                   / static_cast<float>(hair_strands);
+    
+    QVector3D strand_base = crest_base + head.forward * (offset * head_r * 0.15F);
+    QVector3D strand_tip = strand_base + head.up * (head_r * 0.35F) + 
+                           head.forward * (head_r * -0.12F);
+    
+    float wave = std::sin(offset * 3.14159F) * 0.02F;
+    strand_tip += head.right * (wave * head_r);
+    
+    QVector3D strand_color = crest_color * (1.0F + offset * 0.15F);
+    
+    submitter.mesh(getUnitCylinder(),
+                   cylinderBetween(ctx.model, strand_base, strand_tip, head_r * 0.045F),
+                   strand_color, nullptr, 0.7F);
+  }
+}
+
+void CarthageLightHelmetRenderer::renderRivets(const DrawContext &ctx,
+                                               const AttachmentFrame &head,
+                                               ISubmitter &submitter) {
+  float const head_r = head.radius;
+  
+  auto headPoint = [&](const QVector3D &normalized) -> QVector3D {
+    return HumanoidRendererBase::frameLocalPosition(head, normalized);
+  };
+
+  // Decorative bronze rivets around helmet bowl
+  QVector3D rivet_color = m_config.bronze_color * 1.25F;
+  
+  int const rivet_count = 12;
+  for (int i = 0; i < rivet_count; ++i) {
+    float angle = (static_cast<float>(i) / static_cast<float>(rivet_count)) 
+                  * 2.0F * std::numbers::pi_v<float>;
+    
+    float x = std::cos(angle) * 0.85F;
+    float z = std::sin(angle) * 0.85F;
+    
+    QVector3D rivet_pos = headPoint(QVector3D(x, 0.55F, z));
+    
+    QMatrix4x4 rivet_m = ctx.model;
+    rivet_m.translate(rivet_pos);
+    rivet_m.scale(head_r * 0.06F);
+    
+    submitter.mesh(getUnitSphere(), rivet_m, rivet_color, nullptr, 1.0F);
+  }
+}
+
+} // namespace Render::GL

+ 49 - 0
render/equipment/helmets/carthage_light_helmet.h

@@ -0,0 +1,49 @@
+#pragma once
+
+#include "../../humanoid/rig.h"
+#include "../../palette.h"
+#include "../i_equipment_renderer.h"
+#include <QVector3D>
+
+namespace Render::GL {
+
+struct CarthageLightHelmetConfig {
+  QVector3D bronze_color = QVector3D(0.72F, 0.45F, 0.20F);
+  QVector3D leather_color = QVector3D(0.35F, 0.25F, 0.18F);
+  float helmet_height = 0.18F;
+  float brim_width = 0.05F;
+  float cheek_guard_length = 0.12F;
+  bool has_crest = true;
+  bool has_nasal_guard = true;
+  int detail_level = 2; // 0=low, 1=medium, 2=high
+};
+
+class CarthageLightHelmetRenderer : public IEquipmentRenderer {
+public:
+  CarthageLightHelmetRenderer() = default;
+
+  void setConfig(const CarthageLightHelmetConfig &config) { m_config = config; }
+
+  void render(const DrawContext &ctx, const BodyFrames &frames,
+              const HumanoidPalette &palette,
+              const HumanoidAnimationContext &anim,
+              ISubmitter &submitter) override;
+
+private:
+  CarthageLightHelmetConfig m_config;
+
+  void renderBowl(const DrawContext &ctx, const AttachmentFrame &head,
+                  ISubmitter &submitter);
+  void renderBrim(const DrawContext &ctx, const AttachmentFrame &head,
+                  ISubmitter &submitter);
+  void renderCheekGuards(const DrawContext &ctx, const AttachmentFrame &head,
+                         ISubmitter &submitter);
+  void renderNasalGuard(const DrawContext &ctx, const AttachmentFrame &head,
+                        ISubmitter &submitter);
+  void renderCrest(const DrawContext &ctx, const AttachmentFrame &head,
+                   ISubmitter &submitter);
+  void renderRivets(const DrawContext &ctx, const AttachmentFrame &head,
+                    ISubmitter &submitter);
+};
+
+} // namespace Render::GL

+ 1 - 1
render/gl/backend.cpp

@@ -229,7 +229,7 @@ void Backend::execute(const DrawQueue &queue, const Camera &cam) {
               m_cylinderPipeline->m_cylinderUniforms.view_proj, view_proj);
         }
         m_cylinderPipeline->uploadCylinderInstances(instance_count);
-        m_cylinderPipeline->drawCylinders(instance_count);
+        m_cylinderPipeline->draw_cylinders(instance_count);
       }
       continue;
     }

+ 1 - 1
render/gl/backend/backend_impl.h

@@ -21,7 +21,7 @@ void cacheCylinderUniforms(Backend *backend);
 
 void uploadCylinderInstances(Backend *backend, std::size_t count);
 
-void drawCylinders(Backend *backend, std::size_t count);
+void draw_cylinders(Backend *backend, std::size_t count);
 
 void initializeFogPipeline(Backend *backend);
 

+ 1 - 1
render/gl/backend/cylinder_pipeline.cpp

@@ -248,7 +248,7 @@ void CylinderPipeline::uploadCylinderInstances(std::size_t count) {
   glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
-void CylinderPipeline::drawCylinders(std::size_t count) {
+void CylinderPipeline::draw_cylinders(std::size_t count) {
   if ((m_cylinderVao == 0U) || m_cylinderIndexCount == 0 || count == 0) {
     return;
   }

+ 1 - 1
render/gl/backend/cylinder_pipeline.h

@@ -24,7 +24,7 @@ public:
   void beginFrame();
 
   void uploadCylinderInstances(std::size_t count);
-  void drawCylinders(std::size_t count);
+  void draw_cylinders(std::size_t count);
 
   void uploadFogInstances(std::size_t count);
   void drawFog(std::size_t count);

+ 1 - 1
render/gl/persistent_buffer_example.cpp

@@ -58,7 +58,7 @@ void Backend::uploadCylinderInstances(std::size_t count) {
   glBindBuffer(GL_ARRAY_BUFFER, 0);
 }
 
-void Backend::drawCylinders(std::size_t count) {
+void Backend::draw_cylinders(std::size_t count) {
   if (!m_cylinderVao || m_cylinderIndexCount == 0 || count == 0)
     return;
 

+ 9 - 9
render/horse/rig.cpp

@@ -98,7 +98,7 @@ inline auto scaledSphere(const QMatrix4x4 &model, const QVector3D &center,
   return m;
 }
 
-inline void drawCylinder(ISubmitter &out, const QMatrix4x4 &model,
+inline void draw_cylinder(ISubmitter &out, const QMatrix4x4 &model,
                          const QVector3D &a, const QVector3D &b, float radius,
                          const QVector3D &color, float alpha = 1.0F) {
   out.mesh(getUnitCylinder(), cylinderBetween(model, a, b, radius), color,
@@ -452,7 +452,7 @@ void HorseRendererBase::render(const DrawContext &ctx,
         chest_center + QVector3D(side * d.bodyWidth * 0.70F,
                                  -d.bodyHeight * 0.02F, d.bodyLength * 0.06F);
     QVector3D const scapula_mid = lerp(scapula_top, scapula_base, 0.55F);
-    drawCylinder(
+    draw_cylinder(
         out, ctx.model, scapula_top, scapula_mid, d.bodyWidth * 0.18F,
         coatGradient(v.coatColor, 0.82F, 0.16F, coat_seed_a + side * 0.05F));
 
@@ -505,7 +505,7 @@ void HorseRendererBase::render(const DrawContext &ctx,
     QVector3D const jugular_end =
         jugular_start +
         QVector3D(0.0F, -d.bodyHeight * 0.24F, d.bodyLength * 0.06F);
-    drawCylinder(out, ctx.model, jugular_start, jugular_end,
+    draw_cylinder(out, ctx.model, jugular_start, jugular_end,
                  neck_radius * 0.18F, lighten(neck_color_base, 1.08F), 0.85F);
   }
 
@@ -670,13 +670,13 @@ void HorseRendererBase::render(const DrawContext &ctx,
   QVector3D const brow = head_center + QVector3D(0.0F, d.headHeight * 0.38F,
                                                  -d.headLength * 0.28F);
   QVector3D const tack_color = lighten(v.tack_color, 0.9F);
-  drawCylinder(out, ctx.model, bridle_base, cheek_anchor_left,
+  draw_cylinder(out, ctx.model, bridle_base, cheek_anchor_left,
                d.headWidth * 0.07F, tack_color);
-  drawCylinder(out, ctx.model, bridle_base, cheek_anchor_right,
+  draw_cylinder(out, ctx.model, bridle_base, cheek_anchor_right,
                d.headWidth * 0.07F, tack_color);
-  drawCylinder(out, ctx.model, cheek_anchor_left, brow, d.headWidth * 0.05F,
+  draw_cylinder(out, ctx.model, cheek_anchor_left, brow, d.headWidth * 0.05F,
                tack_color);
-  drawCylinder(out, ctx.model, cheek_anchor_right, brow, d.headWidth * 0.05F,
+  draw_cylinder(out, ctx.model, cheek_anchor_right, brow, d.headWidth * 0.05F,
                tack_color);
 
   QVector3D const mane_root =
@@ -733,7 +733,7 @@ void HorseRendererBase::render(const DrawContext &ctx,
         (0.025F + rider_intensity * 0.020F + 0.015F * (1.0F - t));
     p.setX(p.x() + swing);
     float const radius = d.bodyWidth * (0.20F - 0.018F * i);
-    drawCylinder(out, ctx.model, prev_tail, p, radius, tail_color);
+    draw_cylinder(out, ctx.model, prev_tail, p, radius, tail_color);
     prev_tail = p;
   }
 
@@ -850,7 +850,7 @@ void HorseRendererBase::render(const DrawContext &ctx,
         shoulder +
         QVector3D(0.0F, d.bodyWidth * 0.12F,
                   is_rear ? -d.bodyLength * 0.03F : d.bodyLength * 0.02F);
-    drawCylinder(out, ctx.model, girdle_top, socket,
+    draw_cylinder(out, ctx.model, girdle_top, socket,
                  d.bodyWidth * (is_rear ? 0.20F : 0.18F),
                  coatGradient(v.coatColor, is_rear ? 0.70F : 0.80F,
                               is_rear ? -0.20F : 0.22F,

+ 10 - 10
render/humanoid/rig.cpp

@@ -77,13 +77,13 @@ auto HumanoidRendererBase::makeHeadLocalTransform(
   return makeFrameLocalTransform(parent, frame, local_offset, uniform_scale);
 }
 
-void HumanoidRendererBase::getVariant(const DrawContext &ctx, uint32_t seed,
+void HumanoidRendererBase::get_variant(const DrawContext &ctx, uint32_t seed,
                                       HumanoidVariant &v) const {
   QVector3D const team_tint = resolveTeamTint(ctx);
   v.palette = makeHumanoidPalette(team_tint, seed);
 }
 
-void HumanoidRendererBase::customizePose(const DrawContext &,
+void HumanoidRendererBase::customize_pose(const DrawContext &,
                                          const HumanoidAnimationContext &,
                                          uint32_t, HumanoidPose &) const {}
 
@@ -403,7 +403,7 @@ void HumanoidRendererBase::drawCommonBody(const DrawContext &ctx,
                                           ISubmitter &out) const {
   using HP = HumanProportions;
 
-  QVector3D const scaling = getProportionScaling();
+  QVector3D const scaling = get_proportion_scaling();
   float const width_scale = scaling.x();
   float const height_scale = scaling.y();
 
@@ -709,7 +709,7 @@ void HumanoidRendererBase::drawCommonBody(const DrawContext &ctx,
   drawShoulderDecorations(ctx, v, pose, y_top_cover, pose.neck_base.y(),
                           right_axis, out);
 
-  drawHelmet(ctx, v, pose, out);
+  draw_helmet(ctx, v, pose, out);
 
   QVector3D const belt_top = pose.pelvisPos + QVector3D(0.0F, 0.05F, 0.0F);
   QVector3D const belt_bottom = pose.pelvisPos + QVector3D(0.0F, 0.00F, 0.0F);
@@ -725,7 +725,7 @@ void HumanoidRendererBase::draw_armorOverlay(const DrawContext &,
                                              float, float, const QVector3D &,
                                              ISubmitter &) const {}
 
-void HumanoidRendererBase::drawArmor(const DrawContext &,
+void HumanoidRendererBase::draw_armor(const DrawContext &,
                                      const HumanoidVariant &,
                                      const HumanoidPose &,
                                      const HumanoidAnimationContext &,
@@ -737,7 +737,7 @@ void HumanoidRendererBase::drawShoulderDecorations(const DrawContext &,
                                                    float, const QVector3D &,
                                                    ISubmitter &) const {}
 
-void HumanoidRendererBase::drawHelmet(const DrawContext &,
+void HumanoidRendererBase::draw_helmet(const DrawContext &,
                                       const HumanoidVariant &,
                                       const HumanoidPose &,
                                       ISubmitter &) const {}
@@ -1052,10 +1052,10 @@ void HumanoidRendererBase::render(const DrawContext &ctx,
   }
 
   HumanoidVariant variant;
-  getVariant(ctx, seed, variant);
+  get_variant(ctx, seed, variant);
 
   if (!m_proportionScaleCached) {
-    m_cachedProportionScale = getProportionScaling();
+    m_cachedProportionScale = get_proportion_scaling();
     m_proportionScaleCached = true;
   }
   const QVector3D prop_scale = m_cachedProportionScale;
@@ -1220,7 +1220,7 @@ void HumanoidRendererBase::render(const DrawContext &ctx,
       anim_ctx.attack_phase = std::fmod(anim.time, 1.0F);
     }
 
-    customizePose(inst_ctx, anim_ctx, inst_seed, pose);
+    customize_pose(inst_ctx, anim_ctx, inst_seed, pose);
 
     if (anim_ctx.motion_state == HumanoidMotionState::Run) {
       pose.pelvisPos.setZ(pose.pelvisPos.z() - 0.05F);
@@ -1234,7 +1234,7 @@ void HumanoidRendererBase::render(const DrawContext &ctx,
 
     drawCommonBody(inst_ctx, variant, pose, out);
     drawFacialHair(inst_ctx, variant, pose, out);
-    drawArmor(inst_ctx, variant, pose, anim_ctx, out);
+    draw_armor(inst_ctx, variant, pose, anim_ctx, out);
 
     addAttachments(inst_ctx, variant, pose, anim_ctx, out);
   }

+ 5 - 5
render/humanoid/rig.h

@@ -204,14 +204,14 @@ class HumanoidRendererBase {
 public:
   virtual ~HumanoidRendererBase() = default;
 
-  virtual auto getProportionScaling() const -> QVector3D {
+  virtual auto get_proportion_scaling() const -> QVector3D {
     return {1.0F, 1.0F, 1.0F};
   }
 
-  virtual void getVariant(const DrawContext &ctx, uint32_t seed,
+  virtual void get_variant(const DrawContext &ctx, uint32_t seed,
                           HumanoidVariant &v) const;
 
-  virtual void customizePose(const DrawContext &ctx,
+  virtual void customize_pose(const DrawContext &ctx,
                              const HumanoidAnimationContext &anim_ctx,
                              uint32_t seed, HumanoidPose &ioPose) const;
 
@@ -220,10 +220,10 @@ public:
                               const HumanoidAnimationContext &anim_ctx,
                               ISubmitter &out) const;
 
-  virtual void drawHelmet(const DrawContext &ctx, const HumanoidVariant &v,
+  virtual void draw_helmet(const DrawContext &ctx, const HumanoidVariant &v,
                           const HumanoidPose &pose, ISubmitter &out) const;
 
-  virtual void drawArmor(const DrawContext &ctx, const HumanoidVariant &v,
+  virtual void draw_armor(const DrawContext &ctx, const HumanoidVariant &v,
                          const HumanoidPose &pose,
                          const HumanoidAnimationContext &anim,
                          ISubmitter &out) const;