rig.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #pragma once
  2. #include "../entity/registry.h"
  3. #include "../graphics_settings.h"
  4. #include <QMatrix4x4>
  5. #include <QVector3D>
  6. #include <cstdint>
  7. namespace Render::GL {
  8. struct AnimationInputs;
  9. struct HumanoidAnimationContext;
  10. class ISubmitter;
  11. inline auto calculate_horse_lod(float distance) -> HorseLOD;
  12. struct HorseRenderStats {
  13. uint32_t horses_total{0};
  14. uint32_t horses_rendered{0};
  15. uint32_t horses_skipped_lod{0};
  16. uint32_t profiles_computed{0};
  17. uint32_t profiles_cached{0};
  18. uint32_t lod_full{0};
  19. uint32_t lod_reduced{0};
  20. uint32_t lod_minimal{0};
  21. void reset() {
  22. horses_total = 0;
  23. horses_rendered = 0;
  24. horses_skipped_lod = 0;
  25. profiles_computed = 0;
  26. profiles_cached = 0;
  27. lod_full = 0;
  28. lod_reduced = 0;
  29. lod_minimal = 0;
  30. }
  31. };
  32. auto get_horse_render_stats() -> const HorseRenderStats &;
  33. void reset_horse_render_stats();
  34. struct HorseDimensions {
  35. float body_length{};
  36. float body_width{};
  37. float body_height{};
  38. float barrel_center_y{};
  39. float neck_length{};
  40. float neck_rise{};
  41. float head_length{};
  42. float head_width{};
  43. float head_height{};
  44. float muzzle_length{};
  45. float leg_length{};
  46. float hoof_height{};
  47. float tail_length{};
  48. float saddle_height{};
  49. float saddle_thickness{};
  50. float seat_forward_offset{};
  51. float stirrup_drop{};
  52. float stirrup_out{};
  53. float idle_bob_amplitude{};
  54. float move_bob_amplitude{};
  55. };
  56. struct HorseVariant {
  57. QVector3D coat_color;
  58. QVector3D mane_color;
  59. QVector3D tail_color;
  60. QVector3D muzzle_color;
  61. QVector3D hoof_color;
  62. QVector3D saddle_color;
  63. QVector3D blanket_color;
  64. QVector3D tack_color;
  65. };
  66. struct HorseGait {
  67. float cycle_time{};
  68. float front_leg_phase{};
  69. float rear_leg_phase{};
  70. float stride_swing{};
  71. float stride_lift{};
  72. };
  73. struct HorseProfile {
  74. HorseDimensions dims{};
  75. HorseVariant variant;
  76. HorseGait gait{};
  77. };
  78. struct HorseAttachmentFrame {
  79. QVector3D origin{0.0F, 0.0F, 0.0F};
  80. QVector3D right{1.0F, 0.0F, 0.0F};
  81. QVector3D up{0.0F, 1.0F, 0.0F};
  82. QVector3D forward{0.0F, 0.0F, 1.0F};
  83. auto make_local_transform(const QMatrix4x4 &parent,
  84. const QVector3D &local_offset,
  85. float uniform_scale) const -> QMatrix4x4 {
  86. QMatrix4x4 m = parent;
  87. QVector3D const world_pos = origin + right * local_offset.x() +
  88. up * local_offset.y() +
  89. forward * local_offset.z();
  90. m.translate(world_pos);
  91. QMatrix4x4 basis;
  92. basis.setColumn(0, QVector4D(right * uniform_scale, 0.0F));
  93. basis.setColumn(1, QVector4D(up * uniform_scale, 0.0F));
  94. basis.setColumn(2, QVector4D(forward * uniform_scale, 0.0F));
  95. basis.setColumn(3, QVector4D(0.0F, 0.0F, 0.0F, 1.0F));
  96. return m * basis;
  97. }
  98. };
  99. struct HorseBodyFrames {
  100. HorseAttachmentFrame head{};
  101. HorseAttachmentFrame neck_base{};
  102. HorseAttachmentFrame withers{};
  103. HorseAttachmentFrame back_center{};
  104. HorseAttachmentFrame croup{};
  105. HorseAttachmentFrame chest{};
  106. HorseAttachmentFrame barrel{};
  107. HorseAttachmentFrame rump{};
  108. HorseAttachmentFrame tail_base{};
  109. HorseAttachmentFrame muzzle{};
  110. };
  111. struct MountedAttachmentFrame {
  112. QVector3D saddle_center;
  113. QVector3D seat_position;
  114. QVector3D seat_forward;
  115. QVector3D seat_right;
  116. QVector3D seat_up;
  117. QVector3D stirrup_attach_left;
  118. QVector3D stirrup_attach_right;
  119. QVector3D stirrup_bottom_left;
  120. QVector3D stirrup_bottom_right;
  121. QVector3D rein_bit_left;
  122. QVector3D rein_bit_right;
  123. QVector3D bridle_base;
  124. QVector3D ground_offset;
  125. auto stirrup_attach(bool is_left) const -> const QVector3D &;
  126. auto stirrup_bottom(bool is_left) const -> const QVector3D &;
  127. };
  128. struct ReinState {
  129. float slack = 0.0F;
  130. float tension = 0.0F;
  131. };
  132. struct HorseMotionSample {
  133. float phase = 0.0F;
  134. float bob = 0.0F;
  135. bool is_moving = false;
  136. float rider_intensity = 0.0F;
  137. };
  138. auto make_horse_dimensions(uint32_t seed) -> HorseDimensions;
  139. auto make_horse_variant(uint32_t seed, const QVector3D &leather_base,
  140. const QVector3D &cloth_base) -> HorseVariant;
  141. auto make_horse_profile(uint32_t seed, const QVector3D &leather_base,
  142. const QVector3D &cloth_base) -> HorseProfile;
  143. auto get_or_create_cached_horse_profile(
  144. uint32_t seed, const QVector3D &leather_base,
  145. const QVector3D &cloth_base) -> HorseProfile;
  146. void advance_horse_profile_cache_frame();
  147. auto compute_mount_frame(const HorseProfile &profile) -> MountedAttachmentFrame;
  148. auto compute_rein_state(uint32_t horse_seed,
  149. const HumanoidAnimationContext &rider_ctx) -> ReinState;
  150. auto compute_rein_handle(const MountedAttachmentFrame &mount, bool is_left,
  151. float slack, float tension) -> QVector3D;
  152. auto evaluate_horse_motion(HorseProfile &profile, const AnimationInputs &anim,
  153. const HumanoidAnimationContext &rider_ctx)
  154. -> HorseMotionSample;
  155. void apply_mount_vertical_offset(MountedAttachmentFrame &frame, float bob);
  156. inline void scale_horse_dimensions(HorseDimensions &dims, float scale) {
  157. dims.body_length *= scale;
  158. dims.body_width *= scale;
  159. dims.body_height *= scale;
  160. dims.neck_length *= scale;
  161. dims.neck_rise *= scale;
  162. dims.head_length *= scale;
  163. dims.head_width *= scale;
  164. dims.head_height *= scale;
  165. dims.muzzle_length *= scale;
  166. dims.leg_length *= scale;
  167. dims.hoof_height *= scale;
  168. dims.tail_length *= scale;
  169. dims.saddle_thickness *= scale;
  170. dims.seat_forward_offset *= scale;
  171. dims.stirrup_out *= scale;
  172. dims.stirrup_drop *= scale;
  173. dims.barrel_center_y *= scale;
  174. dims.saddle_height *= scale;
  175. dims.idle_bob_amplitude *= scale;
  176. dims.move_bob_amplitude *= scale;
  177. }
  178. class HorseRendererBase {
  179. public:
  180. virtual ~HorseRendererBase() = default;
  181. void render(const DrawContext &ctx, const AnimationInputs &anim,
  182. const HumanoidAnimationContext &rider_ctx, HorseProfile &profile,
  183. const MountedAttachmentFrame *shared_mount,
  184. const ReinState *shared_reins,
  185. const HorseMotionSample *shared_motion, ISubmitter &out,
  186. HorseLOD lod) const;
  187. void render(const DrawContext &ctx, const AnimationInputs &anim,
  188. const HumanoidAnimationContext &rider_ctx, HorseProfile &profile,
  189. const MountedAttachmentFrame *shared_mount,
  190. const ReinState *shared_reins,
  191. const HorseMotionSample *shared_motion, ISubmitter &out) const;
  192. void render_simplified(const DrawContext &ctx, const AnimationInputs &anim,
  193. const HumanoidAnimationContext &rider_ctx,
  194. HorseProfile &profile,
  195. const MountedAttachmentFrame *shared_mount,
  196. const HorseMotionSample *shared_motion,
  197. ISubmitter &out) const;
  198. void render_minimal(const DrawContext &ctx, HorseProfile &profile,
  199. const HorseMotionSample *shared_motion,
  200. ISubmitter &out) const;
  201. protected:
  202. virtual void draw_attachments(const DrawContext &, const AnimationInputs &,
  203. const HumanoidAnimationContext &,
  204. HorseProfile &, const MountedAttachmentFrame &,
  205. float, float, float, const HorseBodyFrames &,
  206. ISubmitter &) const {}
  207. private:
  208. void render_full(const DrawContext &ctx, const AnimationInputs &anim,
  209. const HumanoidAnimationContext &rider_ctx,
  210. HorseProfile &profile,
  211. const MountedAttachmentFrame *shared_mount,
  212. const ReinState *shared_reins,
  213. const HorseMotionSample *shared_motion,
  214. ISubmitter &out) const;
  215. };
  216. inline auto calculate_horse_lod(float distance) -> HorseLOD {
  217. const auto &settings = Render::GraphicsSettings::instance();
  218. if (distance < settings.horse_full_detail_distance()) {
  219. return HorseLOD::Full;
  220. }
  221. if (distance < settings.horse_reduced_detail_distance()) {
  222. return HorseLOD::Reduced;
  223. }
  224. if (distance < settings.horse_minimal_detail_distance()) {
  225. return HorseLOD::Minimal;
  226. }
  227. return HorseLOD::Billboard;
  228. }
  229. } // namespace Render::GL