tool_belt_renderer.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #include "tool_belt_renderer.h"
  2. #include "../../geom/math_utils.h"
  3. #include "../../geom/transforms.h"
  4. #include "../../gl/primitives.h"
  5. #include "../../humanoid/humanoid_specs.h"
  6. #include "../../submitter.h"
  7. #include <QMatrix4x4>
  8. #include <QVector3D>
  9. #include <cmath>
  10. #include <numbers>
  11. namespace Render::GL {
  12. using Render::Geom::cylinder_between;
  13. using Render::Geom::sphere_at;
  14. ToolBeltRenderer::ToolBeltRenderer(const ToolBeltConfig &config)
  15. : m_config(config) {}
  16. void ToolBeltRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
  17. const HumanoidPalette &,
  18. const HumanoidAnimationContext &,
  19. ISubmitter &submitter) {
  20. renderBelt(ctx, frames.waist, submitter);
  21. if (m_config.include_hammer) {
  22. renderHammerLoop(ctx, frames.waist, submitter);
  23. }
  24. if (m_config.include_chisel) {
  25. renderChiselHolder(ctx, frames.waist, submitter);
  26. }
  27. if (m_config.include_pouches) {
  28. renderPouches(ctx, frames.waist, submitter);
  29. }
  30. }
  31. void ToolBeltRenderer::renderBelt(const DrawContext &ctx,
  32. const AttachmentFrame &waist,
  33. ISubmitter &submitter) {
  34. if (waist.radius <= 0.0F) {
  35. return;
  36. }
  37. QVector3D const belt_color = m_config.leather_color;
  38. QVector3D const buckle_color = m_config.metal_color;
  39. const QVector3D &origin = waist.origin;
  40. const QVector3D &right = waist.right;
  41. const QVector3D &forward = waist.forward;
  42. const QVector3D &up = waist.up;
  43. float const waist_r = waist.radius * 1.05F;
  44. float const waist_d =
  45. (waist.depth > 0.0F) ? waist.depth * 0.90F : waist.radius * 0.80F;
  46. constexpr int segs = 16;
  47. constexpr float pi = std::numbers::pi_v<float>;
  48. float const belt_y = -0.02F;
  49. float const belt_thickness = 0.022F;
  50. for (int i = 0; i < segs; ++i) {
  51. float const a1 = (float(i) / segs) * 2.0F * pi;
  52. float const a2 = (float(i + 1) / segs) * 2.0F * pi;
  53. QVector3D const p1 = origin + right * (waist_r * std::sin(a1)) +
  54. forward * (waist_d * std::cos(a1)) + up * belt_y;
  55. QVector3D const p2 = origin + right * (waist_r * std::sin(a2)) +
  56. forward * (waist_d * std::cos(a2)) + up * belt_y;
  57. submitter.mesh(get_unit_cylinder(),
  58. cylinder_between(ctx.model, p1, p2, belt_thickness),
  59. belt_color, nullptr, 1.0F);
  60. }
  61. QVector3D const buckle_pos =
  62. origin + forward * waist.radius * 0.92F - right * 0.05F + up * belt_y;
  63. submitter.mesh(get_unit_sphere(), sphere_at(ctx.model, buckle_pos, 0.030F),
  64. buckle_color, nullptr, 1.0F);
  65. QVector3D const buckle_pin = buckle_pos + right * 0.035F;
  66. submitter.mesh(get_unit_cylinder(),
  67. cylinder_between(ctx.model, buckle_pos, buckle_pin, 0.008F),
  68. buckle_color * 0.85F, nullptr, 1.0F);
  69. }
  70. void ToolBeltRenderer::renderHammerLoop(const DrawContext &ctx,
  71. const AttachmentFrame &waist,
  72. ISubmitter &submitter) {
  73. if (waist.radius <= 0.0F) {
  74. return;
  75. }
  76. QVector3D const loop_color = m_config.leather_color * 0.90F;
  77. QVector3D const hammer_wood = m_config.wood_color;
  78. QVector3D const hammer_metal = m_config.metal_color * 0.92F;
  79. constexpr float pi = std::numbers::pi_v<float>;
  80. float const side_angle = -0.35F * pi;
  81. QVector3D const loop_pos =
  82. waist.origin + waist.right * (waist.radius * std::sin(side_angle)) +
  83. waist.forward * (waist.radius * std::cos(side_angle)) - waist.up * 0.05F;
  84. for (int i = 0; i < 3; ++i) {
  85. float const t = float(i) / 2.0F;
  86. QVector3D const pos = loop_pos - waist.up * (t * 0.10F);
  87. float const r = 0.014F - t * 0.003F;
  88. submitter.mesh(get_unit_sphere(), sphere_at(ctx.model, pos, r), loop_color,
  89. nullptr, 1.0F);
  90. }
  91. QVector3D const hammer_top = loop_pos - waist.up * 0.08F;
  92. QVector3D const hammer_handle_bot = hammer_top - waist.up * 0.12F;
  93. submitter.mesh(
  94. get_unit_cylinder(),
  95. cylinder_between(ctx.model, hammer_top, hammer_handle_bot, 0.008F),
  96. hammer_wood, nullptr, 1.0F);
  97. QVector3D const hammer_head_center = hammer_top + waist.up * 0.015F;
  98. QVector3D const hammer_head_left = hammer_head_center - waist.right * 0.025F;
  99. QVector3D const hammer_head_right = hammer_head_center + waist.right * 0.025F;
  100. submitter.mesh(
  101. get_unit_cylinder(),
  102. cylinder_between(ctx.model, hammer_head_left, hammer_head_right, 0.012F),
  103. hammer_metal, nullptr, 1.0F);
  104. }
  105. void ToolBeltRenderer::renderChiselHolder(const DrawContext &ctx,
  106. const AttachmentFrame &waist,
  107. ISubmitter &submitter) {
  108. if (waist.radius <= 0.0F) {
  109. return;
  110. }
  111. QVector3D const holder_color = m_config.leather_color * 0.88F;
  112. QVector3D const chisel_metal = m_config.metal_color * 0.90F;
  113. constexpr float pi = std::numbers::pi_v<float>;
  114. float const side_angle = 0.30F * pi;
  115. QVector3D const holder_pos =
  116. waist.origin + waist.right * (waist.radius * std::sin(side_angle)) +
  117. waist.forward * (waist.radius * std::cos(side_angle)) - waist.up * 0.04F;
  118. submitter.mesh(get_unit_sphere(), sphere_at(ctx.model, holder_pos, 0.018F),
  119. holder_color, nullptr, 1.0F);
  120. QVector3D const chisel_bot = holder_pos - waist.up * 0.02F;
  121. QVector3D const chisel_top = holder_pos + waist.up * 0.08F;
  122. submitter.mesh(get_unit_cylinder(),
  123. cylinder_between(ctx.model, chisel_bot, chisel_top, 0.006F),
  124. chisel_metal, nullptr, 1.0F);
  125. submitter.mesh(get_unit_sphere(), sphere_at(ctx.model, chisel_top, 0.008F),
  126. chisel_metal * 1.15F, nullptr, 1.0F);
  127. }
  128. void ToolBeltRenderer::renderPouches(const DrawContext &ctx,
  129. const AttachmentFrame &waist,
  130. ISubmitter &submitter) {
  131. if (waist.radius <= 0.0F) {
  132. return;
  133. }
  134. QVector3D const pouch_color = m_config.leather_color * 0.85F;
  135. constexpr float pi = std::numbers::pi_v<float>;
  136. for (int side = 0; side < 2; ++side) {
  137. float const pouch_angle = (side == 0) ? 0.50F * pi : -0.50F * pi;
  138. QVector3D const pouch_pos =
  139. waist.origin +
  140. waist.right * (waist.radius * 0.95F * std::sin(pouch_angle)) +
  141. waist.forward * (waist.radius * 0.85F * std::cos(pouch_angle)) -
  142. waist.up * 0.06F;
  143. for (int i = 0; i < 4; ++i) {
  144. for (int j = 0; j < 3; ++j) {
  145. float const x_off = (float(i) - 1.5F) * 0.015F;
  146. float const y_off = float(j) * 0.022F;
  147. QVector3D const pos = pouch_pos +
  148. waist.right * x_off * (side == 0 ? 1.0F : -1.0F) -
  149. waist.up * y_off;
  150. float const r = 0.012F - float(j) * 0.002F;
  151. submitter.mesh(get_unit_sphere(), sphere_at(ctx.model, pos, r),
  152. pouch_color, nullptr, 1.0F);
  153. }
  154. }
  155. }
  156. }
  157. } // namespace Render::GL