banner_cloth.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include "banner_cloth.h"
  2. #include <cmath>
  3. namespace Render::Geom {
  4. namespace {
  5. constexpr float k_pi = 3.14159265358979F;
  6. }
  7. auto BannerCloth::generate_banner_transform(const QVector3D &center,
  8. float half_width, float half_height,
  9. float depth) -> QMatrix4x4 {
  10. QMatrix4x4 transform;
  11. transform.translate(center);
  12. transform.scale(half_width, half_height, depth);
  13. return transform;
  14. }
  15. auto BannerTassels::generate_bottom_tassels(
  16. const QVector3D &banner_center, float banner_width, float banner_height,
  17. float tassel_length, int tassel_count, float animation_time,
  18. const QVector3D &thread_color, const QVector3D &tip_color) -> TasselSet {
  19. TasselSet result;
  20. result.thread_color = thread_color;
  21. result.tip_color = tip_color;
  22. int const count = std::min(tassel_count, k_max_tassels);
  23. if (count <= 0) {
  24. return result;
  25. }
  26. result.thread_transforms.reserve(count);
  27. result.tip_transforms.reserve(count);
  28. float const bottom_y = banner_center.y() - banner_height * 0.5F;
  29. float const spacing = banner_width / static_cast<float>(count + 1);
  30. float const start_x = banner_center.x() - banner_width * 0.5F + spacing;
  31. constexpr float thread_radius = 0.008F;
  32. constexpr float tip_size = 0.015F;
  33. for (int i = 0; i < count; ++i) {
  34. float const x = start_x + spacing * static_cast<float>(i);
  35. float const phase = animation_time * 2.5F + static_cast<float>(i) * 0.7F;
  36. float const sway = std::sin(phase) * 0.04F;
  37. QVector3D thread_top(x, bottom_y, banner_center.z());
  38. QVector3D thread_bottom(x + sway, bottom_y - tassel_length,
  39. banner_center.z());
  40. QMatrix4x4 thread_transform;
  41. QVector3D const thread_center = (thread_top + thread_bottom) * 0.5F;
  42. thread_transform.translate(thread_center);
  43. thread_transform.scale(thread_radius, tassel_length * 0.5F, thread_radius);
  44. result.thread_transforms.push_back(thread_transform);
  45. QMatrix4x4 tip_transform;
  46. tip_transform.translate(thread_bottom);
  47. tip_transform.scale(tip_size, tip_size, tip_size);
  48. result.tip_transforms.push_back(tip_transform);
  49. }
  50. return result;
  51. }
  52. auto BannerEmbroidery::generate_border_trim(
  53. const QVector3D &banner_center, float half_width, float half_height,
  54. float border_thickness,
  55. const QVector3D &trim_color) -> std::vector<EmbroideryLayer> {
  56. std::vector<EmbroideryLayer> layers;
  57. layers.reserve(4);
  58. float const z_offset = 0.005F;
  59. {
  60. EmbroideryLayer layer;
  61. layer.transform.translate(banner_center.x(),
  62. banner_center.y() + half_height -
  63. border_thickness * 0.5F,
  64. banner_center.z() + z_offset);
  65. layer.transform.scale(half_width + border_thickness,
  66. border_thickness * 0.5F, 0.002F);
  67. layer.color = trim_color;
  68. layer.alpha = 1.0F;
  69. layers.push_back(layer);
  70. }
  71. {
  72. EmbroideryLayer layer;
  73. layer.transform.translate(banner_center.x(),
  74. banner_center.y() - half_height +
  75. border_thickness * 0.5F,
  76. banner_center.z() + z_offset);
  77. layer.transform.scale(half_width + border_thickness,
  78. border_thickness * 0.5F, 0.002F);
  79. layer.color = trim_color;
  80. layer.alpha = 1.0F;
  81. layers.push_back(layer);
  82. }
  83. {
  84. EmbroideryLayer layer;
  85. layer.transform.translate(banner_center.x() - half_width +
  86. border_thickness * 0.5F,
  87. banner_center.y(), banner_center.z() + z_offset);
  88. layer.transform.scale(border_thickness * 0.5F,
  89. half_height - border_thickness, 0.002F);
  90. layer.color = trim_color;
  91. layer.alpha = 1.0F;
  92. layers.push_back(layer);
  93. }
  94. {
  95. EmbroideryLayer layer;
  96. layer.transform.translate(banner_center.x() + half_width -
  97. border_thickness * 0.5F,
  98. banner_center.y(), banner_center.z() + z_offset);
  99. layer.transform.scale(border_thickness * 0.5F,
  100. half_height - border_thickness, 0.002F);
  101. layer.color = trim_color;
  102. layer.alpha = 1.0F;
  103. layers.push_back(layer);
  104. }
  105. return layers;
  106. }
  107. } // namespace Render::Geom