submitter.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #pragma once
  2. #include "draw_queue.h"
  3. #include "gl/primitives.h"
  4. #include "primitive_batch.h"
  5. #include <QMatrix4x4>
  6. #include <QVector3D>
  7. namespace Render::GL {
  8. class Mesh;
  9. class Texture;
  10. } // namespace Render::GL
  11. namespace Render::GL {
  12. class ISubmitter {
  13. public:
  14. virtual ~ISubmitter() = default;
  15. virtual void mesh(Mesh *mesh, const QMatrix4x4 &model, const QVector3D &color,
  16. Texture *tex = nullptr, float alpha = 1.0F,
  17. int material_id = 0) = 0;
  18. virtual void cylinder(const QVector3D &start, const QVector3D &end,
  19. float radius, const QVector3D &color,
  20. float alpha = 1.0F) = 0;
  21. virtual void selection_ring(const QMatrix4x4 &model, float alpha_inner,
  22. float alpha_outer, const QVector3D &color) = 0;
  23. virtual void grid(const QMatrix4x4 &model, const QVector3D &color,
  24. float cell_size, float thickness, float extent) = 0;
  25. virtual void selection_smoke(const QMatrix4x4 &model, const QVector3D &color,
  26. float base_alpha = 0.15F) = 0;
  27. virtual void healing_beam(const QVector3D &start, const QVector3D &end,
  28. const QVector3D &color, float progress,
  29. float beam_width, float intensity, float time) = 0;
  30. virtual void healer_aura(const QVector3D &position, const QVector3D &color,
  31. float radius, float intensity, float time) = 0;
  32. virtual void combat_dust(const QVector3D &position, const QVector3D &color,
  33. float radius, float intensity, float time) = 0;
  34. virtual void stone_impact(const QVector3D &position, const QVector3D &color,
  35. float radius, float intensity, float time) = 0;
  36. virtual void mode_indicator(const QMatrix4x4 &model, int mode_type,
  37. const QVector3D &color, float alpha = 1.0F) = 0;
  38. };
  39. namespace detail {
  40. inline auto decompose_unit_cylinder(const QMatrix4x4 &model, QVector3D &start,
  41. QVector3D &end, float &radius) -> bool {
  42. start = model.map(QVector3D(0.0F, -0.5F, 0.0F));
  43. end = model.map(QVector3D(0.0F, 0.5F, 0.0F));
  44. QVector3D const sx = model.mapVector(QVector3D(1.0F, 0.0F, 0.0F));
  45. QVector3D const sz = model.mapVector(QVector3D(0.0F, 0.0F, 1.0F));
  46. radius = 0.5F * (sx.length() + sz.length());
  47. return radius > 0.0F;
  48. }
  49. } // namespace detail
  50. class QueueSubmitter : public ISubmitter {
  51. public:
  52. explicit QueueSubmitter(DrawQueue *queue) : m_queue(queue) {}
  53. [[nodiscard]] Shader *shader() const { return m_shader; }
  54. void set_shader(Shader *shader) { m_shader = shader; }
  55. void mesh(Mesh *mesh, const QMatrix4x4 &model, const QVector3D &color,
  56. Texture *tex = nullptr, float alpha = 1.0F,
  57. int material_id = 0) override {
  58. if ((m_queue == nullptr) || (mesh == nullptr)) {
  59. return;
  60. }
  61. if (mesh == get_unit_cylinder() && (tex == nullptr) &&
  62. (m_shader == nullptr)) {
  63. QVector3D start;
  64. QVector3D end;
  65. float radius = 0.0F;
  66. if (detail::decompose_unit_cylinder(model, start, end, radius)) {
  67. CylinderCmd cyl;
  68. cyl.start = start;
  69. cyl.end = end;
  70. cyl.radius = radius;
  71. cyl.color = color;
  72. cyl.alpha = alpha;
  73. m_queue->submit(cyl);
  74. return;
  75. }
  76. }
  77. MeshCmd cmd;
  78. cmd.mesh = mesh;
  79. cmd.texture = tex;
  80. cmd.model = model;
  81. cmd.color = color;
  82. cmd.alpha = alpha;
  83. cmd.material_id = material_id;
  84. cmd.shader = m_shader;
  85. m_queue->submit(cmd);
  86. }
  87. void cylinder(const QVector3D &start, const QVector3D &end, float radius,
  88. const QVector3D &color, float alpha = 1.0F) override {
  89. if (m_queue == nullptr) {
  90. return;
  91. }
  92. CylinderCmd cmd;
  93. cmd.start = start;
  94. cmd.end = end;
  95. cmd.radius = radius;
  96. cmd.color = color;
  97. cmd.alpha = alpha;
  98. m_queue->submit(cmd);
  99. }
  100. void selection_ring(const QMatrix4x4 &model, float alpha_inner,
  101. float alpha_outer, const QVector3D &color) override {
  102. if (m_queue == nullptr) {
  103. return;
  104. }
  105. SelectionRingCmd cmd;
  106. cmd.model = model;
  107. cmd.alpha_inner = alpha_inner;
  108. cmd.alpha_outer = alpha_outer;
  109. cmd.color = color;
  110. m_queue->submit(cmd);
  111. }
  112. void grid(const QMatrix4x4 &model, const QVector3D &color, float cell_size,
  113. float thickness, float extent) override {
  114. if (m_queue == nullptr) {
  115. return;
  116. }
  117. GridCmd cmd;
  118. cmd.model = model;
  119. cmd.color = color;
  120. cmd.cell_size = cell_size;
  121. cmd.thickness = thickness;
  122. cmd.extent = extent;
  123. m_queue->submit(cmd);
  124. }
  125. void selection_smoke(const QMatrix4x4 &model, const QVector3D &color,
  126. float base_alpha = 0.15F) override {
  127. if (m_queue == nullptr) {
  128. return;
  129. }
  130. SelectionSmokeCmd cmd;
  131. cmd.model = model;
  132. cmd.color = color;
  133. cmd.base_alpha = base_alpha;
  134. m_queue->submit(cmd);
  135. }
  136. void healing_beam(const QVector3D &start, const QVector3D &end,
  137. const QVector3D &color, float progress, float beam_width,
  138. float intensity, float time) override {
  139. if (m_queue == nullptr) {
  140. return;
  141. }
  142. HealingBeamCmd cmd;
  143. cmd.start_pos = start;
  144. cmd.end_pos = end;
  145. cmd.color = color;
  146. cmd.progress = progress;
  147. cmd.beam_width = beam_width;
  148. cmd.intensity = intensity;
  149. cmd.time = time;
  150. m_queue->submit(cmd);
  151. }
  152. void healer_aura(const QVector3D &position, const QVector3D &color,
  153. float radius, float intensity, float time) override {
  154. if (m_queue == nullptr) {
  155. return;
  156. }
  157. HealerAuraCmd cmd;
  158. cmd.position = position;
  159. cmd.color = color;
  160. cmd.radius = radius;
  161. cmd.intensity = intensity;
  162. cmd.time = time;
  163. m_queue->submit(cmd);
  164. }
  165. void combat_dust(const QVector3D &position, const QVector3D &color,
  166. float radius, float intensity, float time) override {
  167. if (m_queue == nullptr) {
  168. return;
  169. }
  170. CombatDustCmd cmd;
  171. cmd.position = position;
  172. cmd.color = color;
  173. cmd.radius = radius;
  174. cmd.intensity = intensity;
  175. cmd.time = time;
  176. m_queue->submit(cmd);
  177. }
  178. void stone_impact(const QVector3D &position, const QVector3D &color,
  179. float radius, float intensity, float time) override {
  180. if (m_queue == nullptr) {
  181. return;
  182. }
  183. StoneImpactCmd cmd;
  184. cmd.position = position;
  185. cmd.color = color;
  186. cmd.radius = radius;
  187. cmd.intensity = intensity;
  188. cmd.time = time;
  189. m_queue->submit(cmd);
  190. }
  191. void mode_indicator(const QMatrix4x4 &model, int mode_type,
  192. const QVector3D &color, float alpha = 1.0F) override {
  193. if (m_queue == nullptr) {
  194. return;
  195. }
  196. ModeIndicatorCmd cmd;
  197. cmd.model = model;
  198. cmd.mode_type = mode_type;
  199. cmd.color = color;
  200. cmd.alpha = alpha;
  201. m_queue->submit(cmd);
  202. }
  203. private:
  204. DrawQueue *m_queue = nullptr;
  205. Shader *m_shader = nullptr;
  206. };
  207. class BatchingSubmitter : public ISubmitter {
  208. public:
  209. explicit BatchingSubmitter(ISubmitter *fallback,
  210. PrimitiveBatcher *batcher = nullptr)
  211. : m_fallback(fallback), m_batcher(batcher) {}
  212. [[nodiscard]] ISubmitter *fallback_submitter() const { return m_fallback; }
  213. void set_batcher(PrimitiveBatcher *batcher) { m_batcher = batcher; }
  214. void set_enabled(bool enabled) { m_enabled = enabled; }
  215. void mesh(Mesh *mesh, const QMatrix4x4 &model, const QVector3D &color,
  216. Texture *tex = nullptr, float alpha = 1.0F,
  217. int material_id = 0) override {
  218. if (m_enabled && m_batcher != nullptr && tex == nullptr) {
  219. if (mesh == get_unit_sphere()) {
  220. m_batcher->add_sphere(model, color, alpha);
  221. return;
  222. }
  223. if (mesh == get_unit_cylinder()) {
  224. m_batcher->add_cylinder(model, color, alpha);
  225. return;
  226. }
  227. if (mesh == get_unit_cone()) {
  228. m_batcher->add_cone(model, color, alpha);
  229. return;
  230. }
  231. }
  232. if (m_fallback != nullptr) {
  233. m_fallback->mesh(mesh, model, color, tex, alpha, material_id);
  234. }
  235. }
  236. void cylinder(const QVector3D &start, const QVector3D &end, float radius,
  237. const QVector3D &color, float alpha = 1.0F) override {
  238. if (m_fallback != nullptr) {
  239. m_fallback->cylinder(start, end, radius, color, alpha);
  240. }
  241. }
  242. void selection_ring(const QMatrix4x4 &model, float alpha_inner,
  243. float alpha_outer, const QVector3D &color) override {
  244. if (m_fallback != nullptr) {
  245. m_fallback->selection_ring(model, alpha_inner, alpha_outer, color);
  246. }
  247. }
  248. void grid(const QMatrix4x4 &model, const QVector3D &color, float cell_size,
  249. float thickness, float extent) override {
  250. if (m_fallback != nullptr) {
  251. m_fallback->grid(model, color, cell_size, thickness, extent);
  252. }
  253. }
  254. void selection_smoke(const QMatrix4x4 &model, const QVector3D &color,
  255. float base_alpha = 0.15F) override {
  256. if (m_fallback != nullptr) {
  257. m_fallback->selection_smoke(model, color, base_alpha);
  258. }
  259. }
  260. void healing_beam(const QVector3D &start, const QVector3D &end,
  261. const QVector3D &color, float progress, float beam_width,
  262. float intensity, float time) override {
  263. if (m_fallback != nullptr) {
  264. m_fallback->healing_beam(start, end, color, progress, beam_width,
  265. intensity, time);
  266. }
  267. }
  268. void healer_aura(const QVector3D &position, const QVector3D &color,
  269. float radius, float intensity, float time) override {
  270. if (m_fallback != nullptr) {
  271. m_fallback->healer_aura(position, color, radius, intensity, time);
  272. }
  273. }
  274. void combat_dust(const QVector3D &position, const QVector3D &color,
  275. float radius, float intensity, float time) override {
  276. if (m_fallback != nullptr) {
  277. m_fallback->combat_dust(position, color, radius, intensity, time);
  278. }
  279. }
  280. void stone_impact(const QVector3D &position, const QVector3D &color,
  281. float radius, float intensity, float time) override {
  282. if (m_fallback != nullptr) {
  283. m_fallback->stone_impact(position, color, radius, intensity, time);
  284. }
  285. }
  286. void mode_indicator(const QMatrix4x4 &model, int mode_type,
  287. const QVector3D &color, float alpha = 1.0F) override {
  288. if (m_fallback != nullptr) {
  289. m_fallback->mode_indicator(model, mode_type, color, alpha);
  290. }
  291. }
  292. private:
  293. ISubmitter *m_fallback = nullptr;
  294. PrimitiveBatcher *m_batcher = nullptr;
  295. bool m_enabled = true;
  296. };
  297. } // namespace Render::GL