particles.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include <iostream>
  18. #include "irrlichttypes_extrabloated.h"
  19. #include "client/tile.h"
  20. #include "localplayer.h"
  21. #include "../particles.h"
  22. struct ClientEvent;
  23. class ParticleManager;
  24. class ClientEnvironment;
  25. struct MapNode;
  26. struct ContentFeatures;
  27. struct ClientParticleTexture
  28. {
  29. /* per-spawner structure used to store the ParticleTexture structs
  30. * that spawned particles will refer to through ClientParticleTexRef */
  31. ParticleTexture tex;
  32. video::ITexture *ref = nullptr;
  33. ClientParticleTexture() = default;
  34. ClientParticleTexture(const ServerParticleTexture& p, ITextureSource *t):
  35. tex(p),
  36. ref(t->getTextureForMesh(p.string)) {};
  37. };
  38. struct ClientParticleTexRef
  39. {
  40. /* per-particle structure used to avoid massively duplicating the
  41. * fairly large ParticleTexture struct */
  42. ParticleTexture *tex = nullptr;
  43. video::ITexture *ref = nullptr;
  44. ClientParticleTexRef() = default;
  45. /* constructor used by particles spawned from a spawner */
  46. explicit ClientParticleTexRef(ClientParticleTexture &t):
  47. tex(&t.tex), ref(t.ref) {};
  48. /* constructor used for node particles */
  49. explicit ClientParticleTexRef(video::ITexture *tp): ref(tp) {};
  50. };
  51. class ParticleSpawner;
  52. class Particle : public scene::ISceneNode
  53. {
  54. public:
  55. Particle(
  56. IGameDef *gamedef,
  57. LocalPlayer *player,
  58. ClientEnvironment *env,
  59. const ParticleParameters &p,
  60. const ClientParticleTexRef &texture,
  61. v2f texpos,
  62. v2f texsize,
  63. video::SColor color,
  64. ParticleSpawner *parent = nullptr,
  65. std::unique_ptr<ClientParticleTexture> owned_texture = nullptr
  66. );
  67. virtual const aabb3f &getBoundingBox() const
  68. {
  69. return m_box;
  70. }
  71. virtual u32 getMaterialCount() const
  72. {
  73. return 1;
  74. }
  75. virtual video::SMaterial& getMaterial(u32 i)
  76. {
  77. return m_material;
  78. }
  79. virtual void OnRegisterSceneNode();
  80. virtual void render();
  81. void step(float dtime);
  82. bool isExpired ()
  83. { return m_expiration < m_time; }
  84. ParticleSpawner *getParent() { return m_parent; }
  85. private:
  86. void updateLight();
  87. void updateVertices();
  88. void setVertexAlpha(float a);
  89. video::S3DVertex m_vertices[4];
  90. float m_time = 0.0f;
  91. float m_expiration;
  92. ClientEnvironment *m_env;
  93. IGameDef *m_gamedef;
  94. aabb3f m_box;
  95. aabb3f m_collisionbox;
  96. ClientParticleTexRef m_texture;
  97. video::SMaterial m_material;
  98. v2f m_texpos;
  99. v2f m_texsize;
  100. v3f m_pos;
  101. v3f m_velocity;
  102. v3f m_acceleration;
  103. const ParticleParameters m_p;
  104. LocalPlayer *m_player;
  105. //! Color without lighting
  106. video::SColor m_base_color;
  107. //! Final rendered color
  108. video::SColor m_color;
  109. float m_animation_time = 0.0f;
  110. int m_animation_frame = 0;
  111. float m_alpha = 0.0f;
  112. ParticleSpawner *m_parent = nullptr;
  113. // Used if not spawned from a particlespawner
  114. std::unique_ptr<ClientParticleTexture> m_owned_texture;
  115. };
  116. class ParticleSpawner
  117. {
  118. public:
  119. ParticleSpawner(IGameDef *gamedef,
  120. LocalPlayer *player,
  121. const ParticleSpawnerParameters &params,
  122. u16 attached_id,
  123. std::vector<ClientParticleTexture> &&texpool,
  124. ParticleManager *p_manager);
  125. void step(float dtime, ClientEnvironment *env);
  126. bool getExpired() const
  127. { return p.amount <= 0 && p.time != 0; }
  128. bool hasActive() const { return m_active != 0; }
  129. void decrActive() { m_active -= 1; }
  130. private:
  131. void spawnParticle(ClientEnvironment *env, float radius,
  132. const core::matrix4 *attached_absolute_pos_rot_matrix);
  133. size_t m_active;
  134. ParticleManager *m_particlemanager;
  135. float m_time;
  136. IGameDef *m_gamedef;
  137. LocalPlayer *m_player;
  138. ParticleSpawnerParameters p;
  139. std::vector<ClientParticleTexture> m_texpool;
  140. std::vector<float> m_spawntimes;
  141. u16 m_attached_id;
  142. };
  143. /**
  144. * Class doing particle as well as their spawners handling
  145. */
  146. class ParticleManager
  147. {
  148. friend class ParticleSpawner;
  149. public:
  150. ParticleManager(ClientEnvironment* env);
  151. DISABLE_CLASS_COPY(ParticleManager)
  152. ~ParticleManager();
  153. void step (float dtime);
  154. void handleParticleEvent(ClientEvent *event, Client *client,
  155. LocalPlayer *player);
  156. void addDiggingParticles(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
  157. const MapNode &n, const ContentFeatures &f);
  158. void addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
  159. const MapNode &n, const ContentFeatures &f);
  160. void reserveParticleSpace(size_t max_estimate);
  161. /**
  162. * This function is only used by client particle spawners
  163. *
  164. * We don't need to check the particle spawner list because client ID will
  165. * never overlap (u64)
  166. * @return new id
  167. */
  168. u64 generateSpawnerId()
  169. {
  170. return m_next_particle_spawner_id++;
  171. }
  172. protected:
  173. static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f,
  174. ParticleParameters &p, video::ITexture **texture, v2f &texpos,
  175. v2f &texsize, video::SColor *color, u8 tilenum = 0);
  176. void addParticle(std::unique_ptr<Particle> toadd);
  177. private:
  178. void addParticleSpawner(u64 id, std::unique_ptr<ParticleSpawner> toadd);
  179. void deleteParticleSpawner(u64 id);
  180. void stepParticles(float dtime);
  181. void stepSpawners(float dtime);
  182. void clearAll();
  183. std::vector<std::unique_ptr<Particle>> m_particles;
  184. std::unordered_map<u64, std::unique_ptr<ParticleSpawner>> m_particle_spawners;
  185. std::vector<std::unique_ptr<ParticleSpawner>> m_dying_particle_spawners;
  186. // Start the particle spawner ids generated from here after u32_max. lower values are
  187. // for server sent spawners.
  188. u64 m_next_particle_spawner_id = U32_MAX + 1;
  189. ClientEnvironment *m_env;
  190. std::mutex m_particle_list_lock;
  191. std::mutex m_spawner_list_lock;
  192. };