cloak_renderer.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include "cloak_renderer.h"
  2. #include "../../geom/transforms.h"
  3. #include "../../gl/primitives.h"
  4. #include "../../humanoid/humanoid_specs.h"
  5. #include "../../humanoid/rig.h"
  6. #include "../../submitter.h"
  7. #include <QMatrix4x4>
  8. #include <QVector3D>
  9. #include <algorithm>
  10. #include <cmath>
  11. #include <numbers>
  12. namespace Render::GL {
  13. CloakRenderer::CloakRenderer(const CloakConfig &config) : m_config(config) {
  14. m_back_mesh = create_plane_mesh(1.0F, 1.0F, 16);
  15. m_shoulder_mesh = create_plane_mesh(1.0F, 1.0F, 12);
  16. }
  17. void CloakRenderer::set_config(const CloakConfig &config) { m_config = config; }
  18. void CloakRenderer::render(const DrawContext &ctx, const BodyFrames &frames,
  19. const HumanoidPalette &palette,
  20. const HumanoidAnimationContext &anim,
  21. ISubmitter &submitter) {
  22. (void)anim;
  23. (void)palette;
  24. const AttachmentFrame &torso = frames.torso;
  25. const AttachmentFrame &shoulder_l = frames.shoulder_l;
  26. const AttachmentFrame &shoulder_r = frames.shoulder_r;
  27. if (torso.radius <= 0.0F) {
  28. return;
  29. }
  30. QVector3D const cloak_color = palette.cloth;
  31. QVector3D const trim_color = palette.metal;
  32. QVector3D up = torso.up.normalized();
  33. QVector3D right = torso.right.normalized();
  34. QVector3D forward = torso.forward.normalized();
  35. QVector3D back = -forward;
  36. float const torso_r = torso.radius;
  37. float shoulder_span = (shoulder_r.origin - shoulder_l.origin).length();
  38. if (shoulder_span < 1e-4F) {
  39. shoulder_span = torso_r * 3.0F;
  40. }
  41. QVector3D shoulder_mid = (shoulder_l.origin + shoulder_r.origin) * 0.5F;
  42. {
  43. float cape_width = shoulder_span * 1.6F * m_config.width_scale;
  44. float cape_depth = torso_r * 1.8F;
  45. QVector3D cape_anchor = shoulder_mid + up * (torso_r * 0.82F);
  46. QMatrix4x4 cape_model;
  47. cape_model.translate(cape_anchor);
  48. float yaw = std::atan2(forward.x(), forward.z());
  49. cape_model.rotate(yaw * 180.0F / static_cast<float>(std::numbers::pi), 0.0F,
  50. 1.0F, 0.0F);
  51. cape_model.scale(cape_width, 1.0F, cape_depth);
  52. submitter.mesh(m_shoulder_mesh.get(), ctx.model * cape_model, cloak_color,
  53. nullptr, 1.0F, m_config.shoulder_material_id);
  54. }
  55. {
  56. float drape_width = shoulder_span * 1.22F * m_config.width_scale;
  57. float drape_length = torso_r * 4.2F * m_config.length_scale;
  58. QVector3D drape_anchor =
  59. shoulder_mid + up * (torso_r * 0.62F) + back * (torso_r * 0.96F);
  60. QMatrix4x4 drape_model;
  61. drape_model.translate(drape_anchor);
  62. QMatrix4x4 drape_orient;
  63. drape_orient.setColumn(0, QVector4D(right, 0.0F));
  64. drape_orient.setColumn(1, QVector4D(back, 0.0F));
  65. drape_orient.setColumn(2, QVector4D(-up, 0.0F));
  66. drape_orient.setColumn(3, QVector4D(0.0F, 0.0F, 0.0F, 1.0F));
  67. drape_model = drape_model * drape_orient;
  68. drape_model.translate(0.0F, 0.0F, drape_length * 0.5F);
  69. float const drape_bottom_flare = 0.35F;
  70. float const drape_shear = drape_bottom_flare * 0.35F;
  71. QMatrix4x4 flare;
  72. flare.setToIdentity();
  73. flare(0, 2) = drape_shear;
  74. drape_model = drape_model * flare;
  75. drape_model.scale(drape_width, 1.0F, drape_length);
  76. submitter.mesh(m_back_mesh.get(), ctx.model * drape_model, cloak_color,
  77. nullptr, 1.0F, m_config.back_material_id);
  78. }
  79. if (m_config.show_clasp) {
  80. QVector3D clasp_pos =
  81. shoulder_mid + up * (torso_r * 0.5F) + forward * (torso_r * 0.2F);
  82. submitter.mesh(
  83. get_unit_sphere(),
  84. Render::Geom::sphere_at(ctx.model, clasp_pos, torso_r * 0.12F),
  85. trim_color, nullptr, 1.0F, 1);
  86. }
  87. }
  88. } // namespace Render::GL