ClampVelocityModule.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // ClampVelocityModule.cpp
  3. // cocos2d_libs
  4. //
  5. // Created by 徐俊杰 on 2020/4/24.
  6. //
  7. #include "rparticle/Modules/ClampVelocityModule.h"
  8. //#include "UnityPrefix.h"
  9. //#include "Runtime/BaseClasses/ObjectDefines.h"
  10. #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
  11. //#include "rparticle/Modules/ClampVelocityModule.h"
  12. #include "rparticle/ParticleSystemUtils.h"
  13. //#include "Runtime/Misc/BuildSettings.h"
  14. NS_RRP_BEGIN
  15. inline float DampenOutsideLimit (float v, float limit, float dampen)
  16. {
  17. float sgn = Sign (v);
  18. float abs = Abs (v);
  19. if (abs > limit)
  20. abs = Lerp(abs, limit, dampen);
  21. return abs * sgn;
  22. }
  23. ClampVelocityModule::ClampVelocityModule () : ParticleSystemModule(false)
  24. , m_SeparateAxis (false)
  25. , m_InWorldSpace (false)
  26. , m_Dampen (1.0f)
  27. {
  28. }
  29. template<ParticleSystemCurveEvalMode mode>
  30. void MagnitudeUpdateTpl(const MinMaxCurve& magnitude, const ParticleSystemReadOnlyState& roState, ParticleSystemParticles& ps, size_t fromIndex, size_t toIndex, float dampen)
  31. {
  32. for (size_t q = fromIndex; q < toIndex; ++q)
  33. {
  34. float limit = Evaluate<mode> (magnitude, NormalizedTime(ps, q), GenerateRandom(ps.randomSeed[q] + kParticleSystemClampVelocityCurveId)) * roState.GetRenderScale();
  35. Vector3f vel = ps.velocity[q] + ps.animatedVelocity[q];
  36. vel = NormalizeSafe (vel) * DampenOutsideLimit (Magnitude (vel), limit, dampen);
  37. ps.velocity[q] = vel - ps.animatedVelocity[q];
  38. }
  39. }
  40. template<ParticleSystemCurveEvalMode mode>
  41. void MagnitudeUpdatePerAxisTpl(const MinMaxCurve& x, const MinMaxCurve& y, const MinMaxCurve& z, const ParticleSystemReadOnlyState& roState, const ParticleSystemState& state, ParticleSystemParticles& ps, size_t fromIndex, size_t toIndex, float dampen, bool worldSpace)
  42. {
  43. Matrix4x4f matrix;
  44. Matrix4x4f invMatrix;
  45. bool transform;
  46. // if(IS_CONTENT_NEWER_OR_SAME (kUnityVersion4_0_a1))
  47. if(true)
  48. transform = GetTransformationMatrices(matrix, invMatrix, !roState.useLocalSpace, worldSpace, state.localToWorld);
  49. else
  50. transform = false; // Revert to old broken behavior
  51. for (size_t q = fromIndex; q < toIndex; ++q)
  52. {
  53. Vector3f random;
  54. GenerateRandom3(random, ps.randomSeed[q] + kParticleSystemClampVelocityCurveId);
  55. float time = NormalizedTime(ps, q);
  56. Vector3f vel = ps.velocity[q] + ps.animatedVelocity[q];
  57. if (transform)
  58. vel = matrix * vel;
  59. float scale = roState.GetRenderScale();
  60. float limitX = Evaluate<mode>(x, time, random.x) * scale;
  61. float limitY = Evaluate<mode>(y, time, random.y) * scale;
  62. float limitZ = Evaluate<mode>(z, time, random.z) * scale;
  63. vel.x = DampenOutsideLimit(vel.x, limitX, dampen);
  64. vel.y = DampenOutsideLimit(vel.y, limitY, dampen);
  65. vel.z = DampenOutsideLimit(vel.z, limitZ, dampen);
  66. vel -= ps.animatedVelocity[q];
  67. if (transform)
  68. vel = invMatrix * vel;
  69. ps.velocity[q] = vel;
  70. }
  71. }
  72. template<ParticleSystemCurveEvalMode mode>
  73. void DragUpdateTpl(const MinMaxCurve& drag, bool useParticleSize, bool useParticleVelocity, ParticleSystemParticles& ps, size_t fromIndex, size_t toIndex, float dt)
  74. {
  75. int useSize = useParticleSize ? 0xffffffff : 0;
  76. int useVelocity = useParticleVelocity ? 0xffffffff : 0;
  77. for (size_t q = fromIndex; q < toIndex; ++q)
  78. {
  79. float time = NormalizedTime(ps, q);
  80. float random = GenerateRandom(ps.randomSeed[q] + kParticleSystemDragCurveId);
  81. float dragCoefficient = Evaluate<mode>(drag, time, random);
  82. Vector3f vel = ps.velocity[q] + ps.animatedVelocity[q];
  83. float velMagSqr = SqrMagnitude(vel);
  84. float maxDimension = ps.size[q];
  85. // if (ps.uses3DSize)
  86. // {
  87. // maxDimension = math::max(maxDimension, math::max(particleSizes[1].load(q), particleSizes[2].load(q)));
  88. // }
  89. maxDimension *= 0.5f;
  90. float circleArea = (M_PI * maxDimension * maxDimension);
  91. float dragValue = dragCoefficient;
  92. if (useSize)
  93. dragValue *= circleArea;
  94. if (useVelocity)
  95. dragValue *= velMagSqr;
  96. float velMag = sqrt(velMagSqr);
  97. // Vector3f normalizedVel = select(Vector3f(ZERO, ZERO, ZERO), div(vel, velMag), velMag > epsilon_normal_sqrt());
  98. Vector3f normalizedVel;
  99. if (velMag > 0)
  100. normalizedVel = vel / velMag;
  101. velMag = std::max<float>(0, velMag - dragValue * dt);
  102. vel = normalizedVel * velMag;
  103. ps.velocity[q] = vel - ps.animatedVelocity[q];
  104. }
  105. }
  106. void ClampVelocityModule::Update (const ParticleSystemReadOnlyState& roState, const ParticleSystemState& state, ParticleSystemParticles& ps, const size_t fromIndex, const size_t toIndex, float dt)
  107. {
  108. if (m_Dampen > 0.0f)
  109. {
  110. const bool isOptimized = m_X.IsOptimized() && m_Y.IsOptimized() && m_Z.IsOptimized();
  111. float dampen = 1.0f - pow(1.0f - m_Dampen, dt * 30.0f); // use a reference fps of 30, as damping is set between 0 and 1, and without the reference fps, applied damping
  112. // is far too small. if we don't apply dt at all, we get FogBugz case 606420, where damping is fps dependent
  113. if (m_SeparateAxis)
  114. {
  115. if (m_X.minMaxState == kMMCScalar)
  116. MagnitudeUpdatePerAxisTpl<kEMScalar>(m_X, m_Y, m_Z, roState, state, ps, fromIndex, toIndex, dampen, m_InWorldSpace);
  117. else if (isOptimized && m_X.UsesMinMax())
  118. MagnitudeUpdatePerAxisTpl<kEMOptimizedMinMax>(m_X, m_Y, m_Z, roState, state, ps, fromIndex, toIndex, dampen, m_InWorldSpace);
  119. else if (isOptimized)
  120. MagnitudeUpdatePerAxisTpl<kEMOptimized>(m_X, m_Y, m_Z, roState, state, ps, fromIndex, toIndex, dampen, m_InWorldSpace);
  121. else
  122. MagnitudeUpdatePerAxisTpl<kEMSlow>(m_X, m_Y, m_Z, roState, state, ps, fromIndex, toIndex, dampen, m_InWorldSpace);
  123. }
  124. else
  125. {
  126. if (m_Magnitude.minMaxState == kMMCScalar)
  127. MagnitudeUpdateTpl<kEMScalar>(m_Magnitude, roState, ps, fromIndex, toIndex, dampen);
  128. else if (m_Magnitude.IsOptimized() && m_Magnitude.UsesMinMax())
  129. MagnitudeUpdateTpl<kEMOptimizedMinMax>(m_Magnitude, roState, ps, fromIndex, toIndex, dampen);
  130. else if (m_Magnitude.IsOptimized())
  131. MagnitudeUpdateTpl<kEMOptimized>(m_Magnitude, roState, ps, fromIndex, toIndex, dampen);
  132. else
  133. MagnitudeUpdateTpl<kEMSlow>(m_Magnitude, roState, ps, fromIndex, toIndex, dampen);
  134. }
  135. }
  136. // apply air drag
  137. if (m_Drag.GetScalar() != 0.0f)
  138. {
  139. if (m_Drag.minMaxState == kMMCScalar)
  140. DragUpdateTpl<kEMScalar>(m_Drag, m_MultiplyDragByParticleSize, m_MultiplyDragByParticleVelocity, ps, fromIndex, toIndex, dt);
  141. else if (m_Drag.IsOptimized() && m_Drag.UsesMinMax())
  142. DragUpdateTpl<kEMOptimizedMinMax>(m_Drag, m_MultiplyDragByParticleSize, m_MultiplyDragByParticleVelocity, ps, fromIndex, toIndex, dt);
  143. else if (m_Drag.IsOptimized())
  144. DragUpdateTpl<kEMOptimized>(m_Drag, m_MultiplyDragByParticleSize, m_MultiplyDragByParticleVelocity, ps, fromIndex, toIndex, dt);
  145. else
  146. DragUpdateTpl<kEMSlow>(m_Drag, m_MultiplyDragByParticleSize, m_MultiplyDragByParticleVelocity, ps, fromIndex, toIndex, dt);
  147. }
  148. }
  149. void ClampVelocityModule::CheckConsistency ()
  150. {
  151. m_Dampen = clamp<float> (m_Dampen, 0.0f, 1.0f);
  152. m_X.SetScalar(std::max<float> (0.0f, m_X.GetScalar()));
  153. m_Y.SetScalar(std::max<float> (0.0f, m_Y.GetScalar()));
  154. m_Z.SetScalar(std::max<float> (0.0f, m_Z.GetScalar()));
  155. m_Magnitude.SetScalar(std::max<float> (0.0f, m_Magnitude.GetScalar()));
  156. m_Drag.SetScalar(clamp<float> (m_Drag.GetScalar(), 0.0f, 100000.0f));
  157. }
  158. template<class TransferFunction>
  159. void ClampVelocityModule::Transfer (TransferFunction& transfer)
  160. {
  161. ParticleSystemModule::Transfer (transfer);
  162. transfer.Transfer (m_X, "x");
  163. transfer.Transfer (m_Y, "y");
  164. transfer.Transfer (m_Z, "z");
  165. transfer.Transfer (m_Magnitude, "magnitude");
  166. transfer.Transfer (m_SeparateAxis, "separateAxis");
  167. transfer.Transfer (m_InWorldSpace, "inWorldSpace");
  168. transfer.Transfer (m_MultiplyDragByParticleSize, "multiplyDragByParticleSize");
  169. transfer.Transfer (m_MultiplyDragByParticleVelocity, "multiplyDragByParticleVelocity"); transfer.Align ();
  170. transfer.Transfer (m_Dampen, "dampen");
  171. transfer.Transfer (m_Drag, "drag");
  172. }
  173. INSTANTIATE_TEMPLATE_TRANSFER(ClampVelocityModule)
  174. NS_RRP_END