horse_archer_renderer_base.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "horse_archer_renderer_base.h"
  2. #include "../equipment/armor/cloak_renderer.h"
  3. #include "../equipment/equipment_registry.h"
  4. #include "../equipment/weapons/bow_renderer.h"
  5. #include "../equipment/weapons/quiver_renderer.h"
  6. #include "../humanoid/humanoid_math.h"
  7. #include "../humanoid/humanoid_specs.h"
  8. #include "../humanoid/mounted_pose_controller.h"
  9. #include "../palette.h"
  10. #include "../../game/core/component.h"
  11. #include "../../game/core/entity.h"
  12. #include "../../game/systems/nation_id.h"
  13. #include "mounted_knight_pose.h"
  14. #include "renderer_constants.h"
  15. #include <QVector3D>
  16. #include <algorithm>
  17. #include <cmath>
  18. #include <utility>
  19. namespace Render::GL {
  20. namespace {
  21. constexpr QVector3D k_default_proportion_scale{0.80F, 0.88F, 0.88F};
  22. }
  23. HorseArcherRendererBase::HorseArcherRendererBase(
  24. HorseArcherRendererConfig config)
  25. : m_config(std::move(config)) {
  26. m_config.has_bow = m_config.has_bow && !m_config.bow_equipment_id.empty();
  27. if (!m_config.has_bow) {
  28. m_config.bow_equipment_id.clear();
  29. }
  30. m_config.has_quiver =
  31. m_config.has_quiver && !m_config.quiver_equipment_id.empty();
  32. if (!m_config.has_quiver) {
  33. m_config.quiver_equipment_id.clear();
  34. }
  35. m_horseRenderer.set_attachments(m_config.horse_attachments);
  36. cache_equipment();
  37. }
  38. auto HorseArcherRendererBase::get_proportion_scaling() const -> QVector3D {
  39. return k_default_proportion_scale;
  40. }
  41. auto HorseArcherRendererBase::get_mount_scale() const -> float {
  42. return m_config.mount_scale;
  43. }
  44. void HorseArcherRendererBase::adjust_variation(
  45. const DrawContext &, uint32_t, VariationParams &variation) const {
  46. variation.height_scale = 0.88F;
  47. variation.bulk_scale = 0.72F;
  48. variation.stance_width = 0.60F;
  49. variation.arm_swing_amp = 0.45F;
  50. variation.walk_speed_mult = 1.0F;
  51. variation.posture_slump = 0.0F;
  52. variation.shoulder_tilt = 0.0F;
  53. }
  54. void HorseArcherRendererBase::get_variant(const DrawContext &ctx, uint32_t seed,
  55. HumanoidVariant &v) const {
  56. QVector3D const team_tint = resolve_team_tint(ctx);
  57. v.palette = make_humanoid_palette(team_tint, seed);
  58. }
  59. void HorseArcherRendererBase::apply_riding_animation(
  60. MountedPoseController &mounted_controller, MountedAttachmentFrame &mount,
  61. const HumanoidAnimationContext &anim_ctx, HumanoidPose &pose,
  62. const HorseDimensions &dims, const ReinState &reins) const {
  63. (void)pose;
  64. (void)dims;
  65. (void)reins;
  66. const AnimationInputs &anim = anim_ctx.inputs;
  67. if (anim.is_attacking && !anim.is_melee) {
  68. float const attack_phase =
  69. std::fmod(anim.time * ARCHER_INV_ATTACK_CYCLE_TIME, 1.0F);
  70. mounted_controller.ridingBowShot(mount, attack_phase);
  71. } else {
  72. mounted_controller.ridingIdle(mount);
  73. }
  74. }
  75. void HorseArcherRendererBase::draw_equipment(
  76. const DrawContext &ctx, const HumanoidVariant &v, const HumanoidPose &pose,
  77. const HumanoidAnimationContext &anim_ctx, ISubmitter &out) const {
  78. if (m_config.has_bow && m_cached_bow) {
  79. BowRenderConfig bow_config;
  80. bow_config.string_color = QVector3D(0.30F, 0.30F, 0.32F);
  81. bow_config.metal_color = m_config.metal_color;
  82. bow_config.fletching_color = m_config.fletching_color;
  83. bow_config.bow_top_y = HumanProportions::SHOULDER_Y + 0.55F;
  84. bow_config.bow_bot_y = HumanProportions::WAIST_Y - 0.25F;
  85. bow_config.bow_x = 0.0F;
  86. if (auto *bow_renderer = dynamic_cast<BowRenderer *>(m_cached_bow.get())) {
  87. bow_renderer->set_config(bow_config);
  88. }
  89. m_cached_bow->render(ctx, pose.body_frames, v.palette, anim_ctx, out);
  90. }
  91. if (m_config.has_quiver && m_cached_quiver) {
  92. QuiverRenderConfig quiver_config;
  93. quiver_config.fletching_color = m_config.fletching_color;
  94. quiver_config.quiver_radius = HumanProportions::HEAD_RADIUS * 0.45F;
  95. if (auto *quiver_renderer =
  96. dynamic_cast<QuiverRenderer *>(m_cached_quiver.get())) {
  97. quiver_renderer->set_config(quiver_config);
  98. }
  99. m_cached_quiver->render(ctx, pose.body_frames, v.palette, anim_ctx, out);
  100. }
  101. }
  102. void HorseArcherRendererBase::draw_helmet(const DrawContext &ctx,
  103. const HumanoidVariant &v,
  104. const HumanoidPose &pose,
  105. ISubmitter &out) const {
  106. if (m_config.helmet_equipment_id.empty()) {
  107. return;
  108. }
  109. if (m_cached_helmet) {
  110. HumanoidAnimationContext anim_ctx{};
  111. BodyFrames frames = pose.body_frames;
  112. if (ctx.entity != nullptr) {
  113. auto *move = ctx.entity->get_component<Engine::Core::MovementComponent>();
  114. if (move != nullptr) {
  115. float speed_sq = move->vx * move->vx + move->vz * move->vz;
  116. if (speed_sq > 0.0001F && m_config.helmet_offset_moving > 0.0F) {
  117. frames.head.origin +=
  118. frames.head.forward * m_config.helmet_offset_moving;
  119. }
  120. }
  121. }
  122. m_cached_helmet->render(ctx, frames, v.palette, anim_ctx, out);
  123. }
  124. }
  125. void HorseArcherRendererBase::draw_armor(const DrawContext &ctx,
  126. const HumanoidVariant &v,
  127. const HumanoidPose &pose,
  128. const HumanoidAnimationContext &anim,
  129. ISubmitter &out) const {
  130. if (m_config.armor_equipment_id.empty()) {
  131. return;
  132. }
  133. if (m_cached_armor) {
  134. m_cached_armor->render(ctx, pose.body_frames, v.palette, anim, out);
  135. }
  136. if (m_config.has_cloak && m_cached_cloak) {
  137. CloakConfig cloak_config;
  138. cloak_config.primary_color = m_config.cloak_color;
  139. cloak_config.trim_color = m_config.cloak_trim_color;
  140. cloak_config.back_material_id = m_config.cloak_back_material_id;
  141. cloak_config.shoulder_material_id = m_config.cloak_shoulder_material_id;
  142. if (auto *cloak_renderer =
  143. dynamic_cast<CloakRenderer *>(m_cached_cloak.get())) {
  144. cloak_renderer->set_config(cloak_config);
  145. }
  146. m_cached_cloak->render(ctx, pose.body_frames, v.palette, anim, out);
  147. }
  148. }
  149. void HorseArcherRendererBase::cache_equipment() {
  150. auto &registry = EquipmentRegistry::instance();
  151. if (!m_config.bow_equipment_id.empty()) {
  152. m_cached_bow =
  153. registry.get(EquipmentCategory::Weapon, m_config.bow_equipment_id);
  154. }
  155. if (!m_config.quiver_equipment_id.empty()) {
  156. m_cached_quiver =
  157. registry.get(EquipmentCategory::Weapon, m_config.quiver_equipment_id);
  158. }
  159. if (!m_config.helmet_equipment_id.empty()) {
  160. m_cached_helmet =
  161. registry.get(EquipmentCategory::Helmet, m_config.helmet_equipment_id);
  162. }
  163. if (!m_config.armor_equipment_id.empty()) {
  164. m_cached_armor =
  165. registry.get(EquipmentCategory::Armor, m_config.armor_equipment_id);
  166. }
  167. if (!m_config.cloak_equipment_id.empty()) {
  168. m_cached_cloak =
  169. registry.get(EquipmentCategory::Armor, m_config.cloak_equipment_id);
  170. }
  171. }
  172. auto HorseArcherRendererBase::resolve_shader_key(const DrawContext &ctx) const
  173. -> QString {
  174. std::string nation;
  175. if (ctx.entity != nullptr) {
  176. if (auto *unit = ctx.entity->get_component<Engine::Core::UnitComponent>()) {
  177. nation = Game::Systems::nation_id_to_string(unit->nation_id);
  178. }
  179. }
  180. if (!nation.empty()) {
  181. return QString::fromStdString(std::string("horse_archer_") + nation);
  182. }
  183. return QStringLiteral("horse_archer");
  184. }
  185. } // namespace Render::GL