particles.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. Minetest
  3. Copyright (C) 2020 sfan5 <sfan5@live.de>
  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. #include "particles.h"
  17. #include <type_traits>
  18. using namespace ParticleParamTypes;
  19. #define PARAM_PVFN(n) ParticleParamTypes::n##ParameterValue
  20. v2f PARAM_PVFN(pick) (float* f, const v2f a, const v2f b) {
  21. return v2f(
  22. numericalBlend(f[0], a.X, b.X),
  23. numericalBlend(f[1], a.Y, b.Y)
  24. );
  25. }
  26. v3f PARAM_PVFN(pick) (float* f, const v3f a, const v3f b) {
  27. return v3f(
  28. numericalBlend(f[0], a.X, b.X),
  29. numericalBlend(f[1], a.Y, b.Y),
  30. numericalBlend(f[2], a.Z, b.Z)
  31. );
  32. }
  33. v2f PARAM_PVFN(interpolate) (float fac, const v2f a, const v2f b)
  34. { return b.getInterpolated(a, fac); }
  35. v3f PARAM_PVFN(interpolate) (float fac, const v3f a, const v3f b)
  36. { return b.getInterpolated(a, fac); }
  37. #define PARAM_DEF_SRZR(T, wr, rd) \
  38. void PARAM_PVFN(serialize) (std::ostream& os, T v) {wr(os,v); } \
  39. void PARAM_PVFN(deSerialize)(std::istream& is, T& v) {v = rd(is);}
  40. #define PARAM_DEF_NUM(T, wr, rd) PARAM_DEF_SRZR(T, wr, rd) \
  41. T PARAM_PVFN(interpolate)(float fac, const T a, const T b) \
  42. { return numericalBlend<T>(fac,a,b); } \
  43. T PARAM_PVFN(pick) (float* f, const T a, const T b) \
  44. { return numericalBlend<T>(f[0],a,b); }
  45. PARAM_DEF_NUM(u8, writeU8, readU8); PARAM_DEF_NUM(s8, writeS8, readS8);
  46. PARAM_DEF_NUM(u16, writeU16, readU16); PARAM_DEF_NUM(s16, writeS16, readS16);
  47. PARAM_DEF_NUM(u32, writeU32, readU32); PARAM_DEF_NUM(s32, writeS32, readS32);
  48. PARAM_DEF_NUM(f32, writeF32, readF32);
  49. PARAM_DEF_SRZR(v2f, writeV2F32, readV2F32);
  50. PARAM_DEF_SRZR(v3f, writeV3F32, readV3F32);
  51. enum class ParticleTextureFlags : u8 {
  52. /* each value specifies a bit in a bitmask; if the maximum value
  53. * goes above 1<<7 the type of the flags field must be changed
  54. * from u8, which will necessitate a protocol change! */
  55. // the first bit indicates whether the texture is animated
  56. animated = 1,
  57. /* the next three bits indicate the blending mode of the texture
  58. * blendmode is encoded by (flags |= (u8)blend << 1); retrieve with
  59. * (flags & ParticleTextureFlags::blend) >> 1. note that the third
  60. * bit is currently reserved for adding more blend modes in the future */
  61. blend = 0x7 << 1,
  62. };
  63. /* define some shorthand so we don't have to repeat ourselves or use
  64. * decltype everywhere */
  65. using FlagT = std::underlying_type_t<ParticleTextureFlags>;
  66. void ServerParticleTexture::serialize(std::ostream &os, u16 protocol_ver, bool newPropertiesOnly) const
  67. {
  68. /* newPropertiesOnly is used to de/serialize parameters of the legacy texture
  69. * field, which are encoded separately from the texspec string */
  70. FlagT flags = 0;
  71. if (animated)
  72. flags |= FlagT(ParticleTextureFlags::animated);
  73. if (blendmode != BlendMode::alpha)
  74. flags |= FlagT(blendmode) << 1;
  75. serializeParameterValue(os, flags);
  76. alpha.serialize(os);
  77. scale.serialize(os);
  78. if (!newPropertiesOnly)
  79. os << serializeString32(string);
  80. if (animated)
  81. animation.serialize(os, protocol_ver);
  82. }
  83. void ServerParticleTexture::deSerialize(std::istream &is, u16 protocol_ver, bool newPropertiesOnly)
  84. {
  85. FlagT flags = 0;
  86. deSerializeParameterValue(is, flags);
  87. animated = !!(flags & FlagT(ParticleTextureFlags::animated));
  88. blendmode = BlendMode((flags & FlagT(ParticleTextureFlags::blend)) >> 1);
  89. alpha.deSerialize(is);
  90. scale.deSerialize(is);
  91. if (!newPropertiesOnly)
  92. string = deSerializeString32(is);
  93. if (animated)
  94. animation.deSerialize(is, protocol_ver);
  95. }
  96. void ParticleParameters::serialize(std::ostream &os, u16 protocol_ver) const
  97. {
  98. writeV3F32(os, pos);
  99. writeV3F32(os, vel);
  100. writeV3F32(os, acc);
  101. writeF32(os, expirationtime);
  102. writeF32(os, size);
  103. writeU8(os, collisiondetection);
  104. os << serializeString32(texture.string);
  105. writeU8(os, vertical);
  106. writeU8(os, collision_removal);
  107. animation.serialize(os, protocol_ver);
  108. writeU8(os, glow);
  109. writeU8(os, object_collision);
  110. writeU16(os, node.param0);
  111. writeU8(os, node.param2);
  112. writeU8(os, node_tile);
  113. writeV3F32(os, drag);
  114. jitter.serialize(os);
  115. bounce.serialize(os);
  116. }
  117. template <typename T, T (reader)(std::istream& is)>
  118. inline bool streamEndsBeforeParam(T& val, std::istream& is)
  119. {
  120. // This is kinda awful
  121. T tmp = reader(is);
  122. if (is.eof())
  123. return true;
  124. val = tmp;
  125. return false;
  126. }
  127. void ParticleParameters::deSerialize(std::istream &is, u16 protocol_ver)
  128. {
  129. pos = readV3F32(is);
  130. vel = readV3F32(is);
  131. acc = readV3F32(is);
  132. expirationtime = readF32(is);
  133. size = readF32(is);
  134. collisiondetection = readU8(is);
  135. texture.string = deSerializeString32(is);
  136. vertical = readU8(is);
  137. collision_removal = readU8(is);
  138. animation.deSerialize(is, protocol_ver);
  139. glow = readU8(is);
  140. object_collision = readU8(is);
  141. if (streamEndsBeforeParam<u16, readU16>(node.param0, is))
  142. return;
  143. node.param2 = readU8(is);
  144. node_tile = readU8(is);
  145. if (streamEndsBeforeParam<v3f, readV3F32>(drag, is))
  146. return;
  147. jitter.deSerialize(is);
  148. bounce.deSerialize(is);
  149. }