b2Particle.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. * Copyright (c) 2013 Google, Inc.
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #ifndef B2_PARTICLE
  19. #define B2_PARTICLE
  20. #include <Box2D/Common/b2Math.h>
  21. #include <Box2D/Common/b2Settings.h>
  22. #include <Box2D/Common/b2IntrusiveList.h>
  23. struct b2Color;
  24. class b2ParticleGroup;
  25. /// @file
  26. /// The particle type. Can be combined with the | operator.
  27. enum b2ParticleFlag
  28. {
  29. /// Water particle.
  30. b2_waterParticle = 0,
  31. /// Removed after next simulation step.
  32. b2_zombieParticle = 1 << 1,
  33. /// Zero velocity.
  34. b2_wallParticle = 1 << 2,
  35. /// With restitution from stretching.
  36. b2_springParticle = 1 << 3,
  37. /// With restitution from deformation.
  38. b2_elasticParticle = 1 << 4,
  39. /// With viscosity.
  40. b2_viscousParticle = 1 << 5,
  41. /// Without isotropic pressure.
  42. b2_powderParticle = 1 << 6,
  43. /// With surface tension.
  44. b2_tensileParticle = 1 << 7,
  45. /// Mix color between contacting particles.
  46. b2_colorMixingParticle = 1 << 8,
  47. /// Call b2DestructionListener on destruction.
  48. b2_destructionListenerParticle = 1 << 9,
  49. /// Prevents other particles from leaking.
  50. b2_barrierParticle = 1 << 10,
  51. /// Less compressibility.
  52. b2_staticPressureParticle = 1 << 11,
  53. /// Makes pairs or triads with other particles.
  54. b2_reactiveParticle = 1 << 12,
  55. /// With high repulsive force.
  56. b2_repulsiveParticle = 1 << 13,
  57. /// Call b2ContactListener when this particle is about to interact with
  58. /// a rigid body or stops interacting with a rigid body.
  59. /// This results in an expensive operation compared to using
  60. /// b2_fixtureContactFilterParticle to detect collisions between
  61. /// particles.
  62. b2_fixtureContactListenerParticle = 1 << 14,
  63. /// Call b2ContactListener when this particle is about to interact with
  64. /// another particle or stops interacting with another particle.
  65. /// This results in an expensive operation compared to using
  66. /// b2_particleContactFilterParticle to detect collisions between
  67. /// particles.
  68. b2_particleContactListenerParticle = 1 << 15,
  69. /// Call b2ContactFilter when this particle interacts with rigid bodies.
  70. b2_fixtureContactFilterParticle = 1 << 16,
  71. /// Call b2ContactFilter when this particle interacts with other
  72. /// particles.
  73. b2_particleContactFilterParticle = 1 << 17,
  74. };
  75. /// Small color object for each particle
  76. class b2ParticleColor
  77. {
  78. public:
  79. b2ParticleColor() {}
  80. /// Constructor with four elements: r (red), g (green), b (blue), and a
  81. /// (opacity).
  82. /// Each element can be specified 0 to 255.
  83. b2Inline b2ParticleColor(uint8 r, uint8 g, uint8 b, uint8 a)
  84. {
  85. Set(r, g, b, a);
  86. }
  87. /// Constructor that initializes the above four elements with the value of
  88. /// the b2Color object.
  89. b2ParticleColor(const b2Color& color);
  90. /// True when all four color elements equal 0. When true, a particle color
  91. /// buffer isn't allocated by CreateParticle().
  92. ///
  93. bool IsZero() const
  94. {
  95. return !r && !g && !b && !a;
  96. }
  97. /// Used internally to convert the value of b2Color.
  98. ///
  99. b2Color GetColor() const;
  100. /// Sets color for current object using the four elements described above.
  101. ///
  102. b2Inline void Set(uint8 r_, uint8 g_, uint8 b_, uint8 a_)
  103. {
  104. r = r_;
  105. g = g_;
  106. b = b_;
  107. a = a_;
  108. }
  109. /// Initializes the object with the value of the b2Color.
  110. ///
  111. void Set(const b2Color& color);
  112. /// Assign a b2ParticleColor to this instance.
  113. b2ParticleColor& operator = (const b2ParticleColor &color)
  114. {
  115. Set(color.r, color.g, color.b, color.a);
  116. return *this;
  117. }
  118. /// Multiplies r, g, b, a members by s where s is a value between 0.0
  119. /// and 1.0.
  120. b2ParticleColor& operator *= (float32 s)
  121. {
  122. Set((uint8)(r * s), (uint8)(g * s), (uint8)(b * s), (uint8)(a * s));
  123. return *this;
  124. }
  125. /// Scales r, g, b, a members by s where s is a value between 0 and 255.
  126. b2ParticleColor& operator *= (uint8 s)
  127. {
  128. // 1..256 to maintain the complete dynamic range.
  129. const int32 scale = (int32)s + 1;
  130. Set((uint8)(((int32)r * scale) >> k_bitsPerComponent),
  131. (uint8)(((int32)g * scale) >> k_bitsPerComponent),
  132. (uint8)(((int32)b * scale) >> k_bitsPerComponent),
  133. (uint8)(((int32)a * scale) >> k_bitsPerComponent));
  134. return *this;
  135. }
  136. /// Scales r, g, b, a members by s returning the modified b2ParticleColor.
  137. b2ParticleColor operator * (float32 s) const
  138. {
  139. return MultiplyByScalar(s);
  140. }
  141. /// Scales r, g, b, a members by s returning the modified b2ParticleColor.
  142. b2ParticleColor operator * (uint8 s) const
  143. {
  144. return MultiplyByScalar(s);
  145. }
  146. /// Add two colors. This is a non-saturating addition so values
  147. /// overflows will wrap.
  148. b2Inline b2ParticleColor& operator += (const b2ParticleColor &color)
  149. {
  150. r += color.r;
  151. g += color.g;
  152. b += color.b;
  153. a += color.a;
  154. return *this;
  155. }
  156. /// Add two colors. This is a non-saturating addition so values
  157. /// overflows will wrap.
  158. b2ParticleColor operator + (const b2ParticleColor &color) const
  159. {
  160. b2ParticleColor newColor(*this);
  161. newColor += color;
  162. return newColor;
  163. }
  164. /// Subtract a color from this color. This is a subtraction without
  165. /// saturation so underflows will wrap.
  166. b2Inline b2ParticleColor& operator -= (const b2ParticleColor &color)
  167. {
  168. r -= color.r;
  169. g -= color.g;
  170. b -= color.b;
  171. a -= color.a;
  172. return *this;
  173. }
  174. /// Subtract a color from this color returning the result. This is a
  175. /// subtraction without saturation so underflows will wrap.
  176. b2ParticleColor operator - (const b2ParticleColor &color) const
  177. {
  178. b2ParticleColor newColor(*this);
  179. newColor -= color;
  180. return newColor;
  181. }
  182. /// Compare this color with the specified color.
  183. bool operator == (const b2ParticleColor &color) const
  184. {
  185. return r == color.r && g == color.g && b == color.b && a == color.a;
  186. }
  187. /// Mix mixColor with this color using strength to control how much of
  188. /// mixColor is mixed with this color and vice versa. The range of
  189. /// strength is 0..128 where 0 results in no color mixing and 128 results
  190. /// in an equal mix of both colors. strength 0..128 is analogous to an
  191. /// alpha channel value between 0.0f..0.5f.
  192. b2Inline void Mix(b2ParticleColor * const mixColor, const int32 strength)
  193. {
  194. MixColors(this, mixColor, strength);
  195. }
  196. /// Mix colorA with colorB using strength to control how much of
  197. /// colorA is mixed with colorB and vice versa. The range of
  198. /// strength is 0..128 where 0 results in no color mixing and 128 results
  199. /// in an equal mix of both colors. strength 0..128 is analogous to an
  200. /// alpha channel value between 0.0f..0.5f.
  201. static b2Inline void MixColors(b2ParticleColor * const colorA,
  202. b2ParticleColor * const colorB,
  203. const int32 strength)
  204. {
  205. const uint8 dr = (uint8)((strength * (colorB->r - colorA->r)) >>
  206. k_bitsPerComponent);
  207. const uint8 dg = (uint8)((strength * (colorB->g - colorA->g)) >>
  208. k_bitsPerComponent);
  209. const uint8 db = (uint8)((strength * (colorB->b - colorA->b)) >>
  210. k_bitsPerComponent);
  211. const uint8 da = (uint8)((strength * (colorB->a - colorA->a)) >>
  212. k_bitsPerComponent);
  213. colorA->r += dr;
  214. colorA->g += dg;
  215. colorA->b += db;
  216. colorA->a += da;
  217. colorB->r -= dr;
  218. colorB->g -= dg;
  219. colorB->b -= db;
  220. colorB->a -= da;
  221. }
  222. private:
  223. /// Generalization of the multiply operator using a scalar in-place
  224. /// multiplication.
  225. template <typename T>
  226. b2ParticleColor MultiplyByScalar(T s) const
  227. {
  228. b2ParticleColor color(*this);
  229. color *= s;
  230. return color;
  231. }
  232. public:
  233. uint8 r, g, b, a;
  234. protected:
  235. /// Maximum value of a b2ParticleColor component.
  236. static const float32 k_maxValue;
  237. /// 1.0 / k_maxValue.
  238. static const float32 k_inverseMaxValue;
  239. /// Number of bits used to store each b2ParticleColor component.
  240. static const uint8 k_bitsPerComponent;
  241. };
  242. extern b2ParticleColor b2ParticleColor_zero;
  243. /// A particle definition holds all the data needed to construct a particle.
  244. /// You can safely re-use these definitions.
  245. struct b2ParticleDef
  246. {
  247. b2ParticleDef()
  248. {
  249. flags = 0;
  250. position = b2Vec2_zero;
  251. velocity = b2Vec2_zero;
  252. color = b2ParticleColor_zero;
  253. lifetime = 0.0f;
  254. userData = NULL;
  255. group = NULL;
  256. }
  257. #if LIQUIDFUN_EXTERNAL_LANGUAGE_API
  258. /// Set position with direct floats
  259. void SetPosition(float32 x, float32 y);
  260. /// Set color with direct ints.
  261. void SetColor(int32 r, int32 g, int32 b, int32 a);
  262. #endif // LIQUIDFUN_EXTERNAL_LANGUAGE_API
  263. /// \brief Specifies the type of particle (see #b2ParticleFlag).
  264. ///
  265. /// A particle may be more than one type.
  266. /// Multiple types are chained by logical sums, for example:
  267. /// pd.flags = b2_elasticParticle | b2_viscousParticle
  268. uint32 flags;
  269. /// The world position of the particle.
  270. b2Vec2 position;
  271. /// The linear velocity of the particle in world co-ordinates.
  272. b2Vec2 velocity;
  273. /// The color of the particle.
  274. b2ParticleColor color;
  275. /// Lifetime of the particle in seconds. A value <= 0.0f indicates a
  276. /// particle with infinite lifetime.
  277. float32 lifetime;
  278. /// Use this to store application-specific body data.
  279. void* userData;
  280. /// An existing particle group to which the particle will be added.
  281. b2ParticleGroup* group;
  282. };
  283. /// A helper function to calculate the optimal number of iterations.
  284. int32 b2CalculateParticleIterations(
  285. float32 gravity, float32 radius, float32 timeStep);
  286. /// Handle to a particle. Particle indices are ephemeral: the same index might
  287. /// refer to a different particle, from frame-to-frame. If you need to keep a
  288. /// reference to a particular particle across frames, you should acquire a
  289. /// b2ParticleHandle. Use #b2ParticleSystem::GetParticleHandleFromIndex() to
  290. /// retrieve the b2ParticleHandle of a particle from the particle system.
  291. class b2ParticleHandle : public b2TypedIntrusiveListNode<b2ParticleHandle>
  292. {
  293. // Allow b2ParticleSystem to use SetIndex() to associate particle handles
  294. // with particle indices.
  295. friend class b2ParticleSystem;
  296. public:
  297. /// Initialize the index associated with the handle to an invalid index.
  298. b2ParticleHandle() : m_index(b2_invalidParticleIndex) { }
  299. /// Empty destructor.
  300. ~b2ParticleHandle() { }
  301. /// Get the index of the particle associated with this handle.
  302. int32 GetIndex() const { return m_index; }
  303. private:
  304. /// Set the index of the particle associated with this handle.
  305. void SetIndex(int32 index) { m_index = index; }
  306. private:
  307. // Index of the particle within the particle system.
  308. int32 m_index;
  309. };
  310. #if LIQUIDFUN_EXTERNAL_LANGUAGE_API
  311. inline void b2ParticleDef::SetPosition(float32 x, float32 y)
  312. {
  313. position.Set(x, y);
  314. }
  315. inline void b2ParticleDef::SetColor(int32 r, int32 g, int32 b, int32 a)
  316. {
  317. color.Set((uint8)r, (uint8)g, (uint8)b, (uint8)a);
  318. }
  319. #endif // LIQUIDFUN_EXTERNAL_LANGUAGE_API
  320. #endif