unit_render_cache.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "unit_render_cache.h"
  2. #include "../game/core/component.h"
  3. #include "../game/core/entity.h"
  4. #include "../game/units/spawn_type.h"
  5. #include <QMatrix4x4>
  6. namespace Render {
  7. auto UnitRenderCache::get_or_create(std::uint32_t entity_id,
  8. Engine::Core::Entity *entity,
  9. std::uint32_t frame) -> CachedUnitData & {
  10. auto [it, inserted] = m_cache.emplace(entity_id, CachedUnitData{});
  11. auto &data = it->second;
  12. data.entity_id = entity_id;
  13. data.last_seen_frame = frame;
  14. if (inserted || data.entity != entity) {
  15. data.entity = entity;
  16. data.model_matrix_valid = false;
  17. }
  18. if (entity == nullptr) {
  19. data.transform = nullptr;
  20. data.unit = nullptr;
  21. data.renderable = nullptr;
  22. data.movement = nullptr;
  23. data.renderer_key.clear();
  24. return data;
  25. }
  26. auto *new_transform =
  27. entity->get_component<Engine::Core::TransformComponent>();
  28. auto *new_unit = entity->get_component<Engine::Core::UnitComponent>();
  29. auto *new_renderable =
  30. entity->get_component<Engine::Core::RenderableComponent>();
  31. auto *new_movement = entity->get_component<Engine::Core::MovementComponent>();
  32. if (data.transform != new_transform) {
  33. data.model_matrix_valid = false;
  34. }
  35. data.transform = new_transform;
  36. data.unit = new_unit;
  37. data.renderable = new_renderable;
  38. data.movement = new_movement;
  39. if (data.renderable != nullptr && !data.renderable->renderer_id.empty()) {
  40. data.renderer_key = data.renderable->renderer_id;
  41. } else if (data.unit != nullptr) {
  42. data.renderer_key = Game::Units::spawn_typeToString(data.unit->spawn_type);
  43. } else {
  44. data.renderer_key.clear();
  45. }
  46. return data;
  47. }
  48. void UnitRenderCache::prune(std::uint32_t current_frame,
  49. std::uint32_t max_age) {
  50. auto it = m_cache.begin();
  51. while (it != m_cache.end()) {
  52. if (current_frame - it->second.last_seen_frame > max_age) {
  53. it = m_cache.erase(it);
  54. } else {
  55. ++it;
  56. }
  57. }
  58. }
  59. auto UnitRenderCache::update_model_matrix(CachedUnitData &data) -> bool {
  60. if (data.transform == nullptr) {
  61. return false;
  62. }
  63. const auto &pos = data.transform->position;
  64. const auto &rot = data.transform->rotation;
  65. const auto &sc = data.transform->scale;
  66. if (data.model_matrix_valid && pos.x == data.last_pos_x &&
  67. pos.y == data.last_pos_y && pos.z == data.last_pos_z &&
  68. rot.x == data.last_rot_x && rot.y == data.last_rot_y &&
  69. rot.z == data.last_rot_z && sc.x == data.last_scale_x &&
  70. sc.y == data.last_scale_y && sc.z == data.last_scale_z) {
  71. return false;
  72. }
  73. QMatrix4x4 m;
  74. m.translate(pos.x, pos.y, pos.z);
  75. m.rotate(rot.x, 1.0F, 0.0F, 0.0F);
  76. m.rotate(rot.y, 0.0F, 1.0F, 0.0F);
  77. m.rotate(rot.z, 0.0F, 0.0F, 1.0F);
  78. m.scale(sc.x, sc.y, sc.z);
  79. data.model_matrix = m;
  80. data.last_pos_x = pos.x;
  81. data.last_pos_y = pos.y;
  82. data.last_pos_z = pos.z;
  83. data.last_rot_x = rot.x;
  84. data.last_rot_y = rot.y;
  85. data.last_rot_z = rot.z;
  86. data.last_scale_x = sc.x;
  87. data.last_scale_y = sc.y;
  88. data.last_scale_z = sc.z;
  89. data.model_matrix_valid = true;
  90. return true;
  91. }
  92. auto ModelMatrixCache::get_or_create(
  93. std::uint32_t entity_id, Engine::Core::TransformComponent *transform,
  94. std::uint32_t frame) -> const QMatrix4x4 & {
  95. auto &entry = m_cache[entity_id];
  96. entry.last_seen_frame = frame;
  97. if (transform == nullptr) {
  98. return entry.matrix;
  99. }
  100. const auto &pos = transform->position;
  101. const auto &rot = transform->rotation;
  102. const auto &sc = transform->scale;
  103. if (entry.valid && pos.x == entry.last_pos_x && pos.y == entry.last_pos_y &&
  104. pos.z == entry.last_pos_z && rot.x == entry.last_rot_x &&
  105. rot.y == entry.last_rot_y && rot.z == entry.last_rot_z &&
  106. sc.x == entry.last_scale_x && sc.y == entry.last_scale_y &&
  107. sc.z == entry.last_scale_z) {
  108. return entry.matrix;
  109. }
  110. QMatrix4x4 m;
  111. m.translate(pos.x, pos.y, pos.z);
  112. m.rotate(rot.x, 1.0F, 0.0F, 0.0F);
  113. m.rotate(rot.y, 0.0F, 1.0F, 0.0F);
  114. m.rotate(rot.z, 0.0F, 0.0F, 1.0F);
  115. m.scale(sc.x, sc.y, sc.z);
  116. entry.matrix = m;
  117. entry.last_pos_x = pos.x;
  118. entry.last_pos_y = pos.y;
  119. entry.last_pos_z = pos.z;
  120. entry.last_rot_x = rot.x;
  121. entry.last_rot_y = rot.y;
  122. entry.last_rot_z = rot.z;
  123. entry.last_scale_x = sc.x;
  124. entry.last_scale_y = sc.y;
  125. entry.last_scale_z = sc.z;
  126. entry.valid = true;
  127. return entry.matrix;
  128. }
  129. void ModelMatrixCache::prune(std::uint32_t current_frame,
  130. std::uint32_t max_age) {
  131. auto it = m_cache.begin();
  132. while (it != m_cache.end()) {
  133. if (current_frame - it->second.last_seen_frame > max_age) {
  134. it = m_cache.erase(it);
  135. } else {
  136. ++it;
  137. }
  138. }
  139. }
  140. } // namespace Render