ParticleSystemCurves.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. // ParticleSystemCurves.cpp
  3. // cocos2d_libs
  4. //
  5. // Created by 徐俊杰 on 2020/4/24.
  6. //
  7. #include "rparticle/ParticleSystemCurves.h"
  8. //#include "UnityPrefix.h"
  9. #include "rparticle/ParticleSystemCurves.h"
  10. #include "rparticle/Math/Polynomials.h"
  11. //#include "Runtime/Math/Vector2.h"
  12. //#include "Runtime/BaseClasses/ObjectDefines.h"
  13. #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h"
  14. NS_RRP_BEGIN
  15. // Calculates the min max range of an animation curve analytically
  16. static void CalculateCurveRangesValue(Vector2f& minMaxValue, const AnimationCurve& curve)
  17. {
  18. const int keyCount = curve.GetKeyCount();
  19. if (keyCount == 0)
  20. return;
  21. if (keyCount == 1)
  22. {
  23. CalculateMinMax(minMaxValue, curve.GetKey(0).value);
  24. }
  25. else
  26. {
  27. int segmentCount = keyCount - 1;
  28. CalculateMinMax(minMaxValue, curve.GetKey(0).value);
  29. for (int i = 0;i<segmentCount;i++)
  30. {
  31. DebugAssert(i+1 < keyCount);
  32. AnimationCurve::Cache cache;
  33. curve.CalculateCacheData(cache, i, i + 1, 0.0F);
  34. // Differentiate polynomial
  35. float a = 3.0f * cache.coeff[0];
  36. float b = 2.0f * cache.coeff[1];
  37. float c = 1.0f * cache.coeff[2];
  38. const float start = curve.GetKey(i).time;
  39. const float end = curve.GetKey(i+1).time;
  40. float roots[2];
  41. int numRoots = QuadraticPolynomialRootsGeneric(a, b, c, roots[0], roots[1]);
  42. for(int r = 0; r < numRoots; r++)
  43. if((roots[r] >= 0.0f) && ((roots[r] + start) < end))
  44. CalculateMinMax(minMaxValue, Polynomial::EvalSegment(roots[r], cache.coeff));
  45. CalculateMinMax(minMaxValue, Polynomial::EvalSegment(end-start, cache.coeff));
  46. }
  47. }
  48. }
  49. bool BuildCurves (MinMaxOptimizedPolyCurves& polyCurves, const MinMaxAnimationCurves& editorCurves, float scalar, short minMaxState)
  50. {
  51. bool isOptimizedCurve = polyCurves.max.BuildOptimizedCurve(editorCurves.max, scalar);
  52. if ((minMaxState != kMMCTwoCurves) && (minMaxState != kMMCTwoConstants))
  53. isOptimizedCurve = isOptimizedCurve && polyCurves.min.BuildOptimizedCurve(editorCurves.max, scalar);
  54. else
  55. isOptimizedCurve = isOptimizedCurve && polyCurves.min.BuildOptimizedCurve(editorCurves.min, scalar);
  56. return isOptimizedCurve;
  57. }
  58. void BuildCurves (MinMaxPolyCurves& polyCurves, const MinMaxAnimationCurves& editorCurves, float scalar, short minMaxState)
  59. {
  60. polyCurves.max.BuildCurve(editorCurves.max, scalar);
  61. if ((minMaxState != kMMCTwoCurves) && (minMaxState != kMMCTwoConstants))
  62. polyCurves.min.BuildCurve(editorCurves.max, scalar);
  63. else
  64. polyCurves.min.BuildCurve(editorCurves.min, scalar);
  65. }
  66. bool CurvesSupportProcedural (const MinMaxAnimationCurves& editorCurves, short minMaxState)
  67. {
  68. bool isValid = PolynomialCurve::IsValidCurve(editorCurves.max);
  69. if ((minMaxState != kMMCTwoCurves) && (minMaxState != kMMCTwoConstants))
  70. return isValid;
  71. else
  72. return isValid && PolynomialCurve::IsValidCurve(editorCurves.min);
  73. }
  74. void MinMaxOptimizedPolyCurves::Integrate ()
  75. {
  76. max.Integrate ();
  77. min.Integrate ();
  78. }
  79. void MinMaxOptimizedPolyCurves::DoubleIntegrate ()
  80. {
  81. max.DoubleIntegrate ();
  82. min.DoubleIntegrate ();
  83. }
  84. Vector2f MinMaxOptimizedPolyCurves::FindMinMaxIntegrated()
  85. {
  86. Vector2f minRange = min.FindMinMaxIntegrated();
  87. Vector2f maxRange = max.FindMinMaxIntegrated();
  88. Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y));
  89. return result;
  90. }
  91. Vector2f MinMaxOptimizedPolyCurves::FindMinMaxDoubleIntegrated()
  92. {
  93. Vector2f minRange = min.FindMinMaxDoubleIntegrated();
  94. Vector2f maxRange = max.FindMinMaxDoubleIntegrated();
  95. Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y));
  96. return result;
  97. }
  98. void MinMaxPolyCurves::Integrate ()
  99. {
  100. max.Integrate ();
  101. min.Integrate ();
  102. }
  103. void MinMaxPolyCurves::DoubleIntegrate ()
  104. {
  105. max.DoubleIntegrate ();
  106. min.DoubleIntegrate ();
  107. }
  108. Vector2f MinMaxPolyCurves::FindMinMaxIntegrated()
  109. {
  110. Vector2f minRange = min.FindMinMaxIntegrated();
  111. Vector2f maxRange = max.FindMinMaxIntegrated();
  112. Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y));
  113. return result;
  114. }
  115. Vector2f MinMaxPolyCurves::FindMinMaxDoubleIntegrated()
  116. {
  117. Vector2f minRange = min.FindMinMaxDoubleIntegrated();
  118. Vector2f maxRange = max.FindMinMaxDoubleIntegrated();
  119. Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y));
  120. return result;
  121. }
  122. MinMaxCurve::MinMaxCurve ()
  123. : scalar (1.0f)
  124. , minMaxState (kMMCScalar)
  125. , isOptimizedCurve(false)
  126. {
  127. SetPolynomialCurveToValue (editorCurves.max, polyCurves.max, 1.0f);
  128. SetPolynomialCurveToValue (editorCurves.min, polyCurves.min, 0.0f);
  129. }
  130. Vector2f MinMaxCurve::FindMinMax() const
  131. {
  132. Vector2f result = Vector2f(std::numeric_limits<float>::infinity (), -std::numeric_limits<float>::infinity ());
  133. CalculateCurveRangesValue(result, editorCurves.max);
  134. if((minMaxState == kMMCTwoCurves) || (minMaxState == kMMCTwoConstants))
  135. CalculateCurveRangesValue(result, editorCurves.min);
  136. return result * GetScalar();
  137. }
  138. Vector2f MinMaxCurve::FindMinMaxIntegrated() const
  139. {
  140. if(IsOptimized())
  141. {
  142. MinMaxOptimizedPolyCurves integrated = polyCurves;
  143. integrated.Integrate();
  144. return integrated.FindMinMaxIntegrated();
  145. }
  146. else
  147. {
  148. DebugAssert(CurvesSupportProcedural (editorCurves, minMaxState));
  149. MinMaxPolyCurves integrated;
  150. BuildCurves(integrated, editorCurves, GetScalar(), minMaxState);
  151. integrated.Integrate();
  152. return integrated.FindMinMaxIntegrated();
  153. }
  154. }
  155. Vector2f MinMaxCurve::FindMinMaxDoubleIntegrated() const
  156. {
  157. if(IsOptimized())
  158. {
  159. MinMaxOptimizedPolyCurves doubleIntegrated = polyCurves;
  160. doubleIntegrated.DoubleIntegrate();
  161. return doubleIntegrated.FindMinMaxDoubleIntegrated();
  162. }
  163. else
  164. {
  165. DebugAssert(CurvesSupportProcedural (editorCurves, minMaxState));
  166. MinMaxPolyCurves doubleIntegrated;
  167. BuildCurves(doubleIntegrated, editorCurves, GetScalar(), minMaxState);
  168. doubleIntegrated.DoubleIntegrate();
  169. return doubleIntegrated.FindMinMaxDoubleIntegrated();
  170. }
  171. }
  172. template<class TransferFunction>
  173. void MinMaxCurve::Transfer (TransferFunction& transfer)
  174. {
  175. transfer.Transfer (scalar, "scalar");
  176. transfer.Transfer (editorCurves.max, "maxCurve");
  177. transfer.Transfer (editorCurves.min, "minCurve");
  178. TRANSFER (minMaxState); transfer.Align ();
  179. if (transfer.IsReading ())
  180. isOptimizedCurve = BuildCurves(polyCurves, editorCurves, scalar, minMaxState);
  181. }
  182. INSTANTIATE_TEMPLATE_TRANSFER(MinMaxCurve)
  183. NS_RRP_END