// // ParticleSystemCurves.cpp // cocos2d_libs // // Created by 徐俊杰 on 2020/4/24. // #include "rparticle/ParticleSystemCurves.h" //#include "UnityPrefix.h" #include "rparticle/ParticleSystemCurves.h" #include "rparticle/Math/Polynomials.h" //#include "Runtime/Math/Vector2.h" //#include "Runtime/BaseClasses/ObjectDefines.h" #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h" NS_RRP_BEGIN // Calculates the min max range of an animation curve analytically static void CalculateCurveRangesValue(Vector2f& minMaxValue, const AnimationCurve& curve) { const int keyCount = curve.GetKeyCount(); if (keyCount == 0) return; if (keyCount == 1) { CalculateMinMax(minMaxValue, curve.GetKey(0).value); } else { int segmentCount = keyCount - 1; CalculateMinMax(minMaxValue, curve.GetKey(0).value); for (int i = 0;i= 0.0f) && ((roots[r] + start) < end)) CalculateMinMax(minMaxValue, Polynomial::EvalSegment(roots[r], cache.coeff)); CalculateMinMax(minMaxValue, Polynomial::EvalSegment(end-start, cache.coeff)); } } } bool BuildCurves (MinMaxOptimizedPolyCurves& polyCurves, const MinMaxAnimationCurves& editorCurves, float scalar, short minMaxState) { bool isOptimizedCurve = polyCurves.max.BuildOptimizedCurve(editorCurves.max, scalar); if ((minMaxState != kMMCTwoCurves) && (minMaxState != kMMCTwoConstants)) isOptimizedCurve = isOptimizedCurve && polyCurves.min.BuildOptimizedCurve(editorCurves.max, scalar); else isOptimizedCurve = isOptimizedCurve && polyCurves.min.BuildOptimizedCurve(editorCurves.min, scalar); return isOptimizedCurve; } void BuildCurves (MinMaxPolyCurves& polyCurves, const MinMaxAnimationCurves& editorCurves, float scalar, short minMaxState) { polyCurves.max.BuildCurve(editorCurves.max, scalar); if ((minMaxState != kMMCTwoCurves) && (minMaxState != kMMCTwoConstants)) polyCurves.min.BuildCurve(editorCurves.max, scalar); else polyCurves.min.BuildCurve(editorCurves.min, scalar); } bool CurvesSupportProcedural (const MinMaxAnimationCurves& editorCurves, short minMaxState) { bool isValid = PolynomialCurve::IsValidCurve(editorCurves.max); if ((minMaxState != kMMCTwoCurves) && (minMaxState != kMMCTwoConstants)) return isValid; else return isValid && PolynomialCurve::IsValidCurve(editorCurves.min); } void MinMaxOptimizedPolyCurves::Integrate () { max.Integrate (); min.Integrate (); } void MinMaxOptimizedPolyCurves::DoubleIntegrate () { max.DoubleIntegrate (); min.DoubleIntegrate (); } Vector2f MinMaxOptimizedPolyCurves::FindMinMaxIntegrated() { Vector2f minRange = min.FindMinMaxIntegrated(); Vector2f maxRange = max.FindMinMaxIntegrated(); Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y)); return result; } Vector2f MinMaxOptimizedPolyCurves::FindMinMaxDoubleIntegrated() { Vector2f minRange = min.FindMinMaxDoubleIntegrated(); Vector2f maxRange = max.FindMinMaxDoubleIntegrated(); Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y)); return result; } void MinMaxPolyCurves::Integrate () { max.Integrate (); min.Integrate (); } void MinMaxPolyCurves::DoubleIntegrate () { max.DoubleIntegrate (); min.DoubleIntegrate (); } Vector2f MinMaxPolyCurves::FindMinMaxIntegrated() { Vector2f minRange = min.FindMinMaxIntegrated(); Vector2f maxRange = max.FindMinMaxIntegrated(); Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y)); return result; } Vector2f MinMaxPolyCurves::FindMinMaxDoubleIntegrated() { Vector2f minRange = min.FindMinMaxDoubleIntegrated(); Vector2f maxRange = max.FindMinMaxDoubleIntegrated(); Vector2f result = Vector2f(std::min(minRange.x, maxRange.x), std::max(minRange.y, maxRange.y)); return result; } MinMaxCurve::MinMaxCurve () : scalar (1.0f) , minMaxState (kMMCScalar) , isOptimizedCurve(false) { SetPolynomialCurveToValue (editorCurves.max, polyCurves.max, 1.0f); SetPolynomialCurveToValue (editorCurves.min, polyCurves.min, 0.0f); } Vector2f MinMaxCurve::FindMinMax() const { Vector2f result = Vector2f(std::numeric_limits::infinity (), -std::numeric_limits::infinity ()); CalculateCurveRangesValue(result, editorCurves.max); if((minMaxState == kMMCTwoCurves) || (minMaxState == kMMCTwoConstants)) CalculateCurveRangesValue(result, editorCurves.min); return result * GetScalar(); } Vector2f MinMaxCurve::FindMinMaxIntegrated() const { if(IsOptimized()) { MinMaxOptimizedPolyCurves integrated = polyCurves; integrated.Integrate(); return integrated.FindMinMaxIntegrated(); } else { DebugAssert(CurvesSupportProcedural (editorCurves, minMaxState)); MinMaxPolyCurves integrated; BuildCurves(integrated, editorCurves, GetScalar(), minMaxState); integrated.Integrate(); return integrated.FindMinMaxIntegrated(); } } Vector2f MinMaxCurve::FindMinMaxDoubleIntegrated() const { if(IsOptimized()) { MinMaxOptimizedPolyCurves doubleIntegrated = polyCurves; doubleIntegrated.DoubleIntegrate(); return doubleIntegrated.FindMinMaxDoubleIntegrated(); } else { DebugAssert(CurvesSupportProcedural (editorCurves, minMaxState)); MinMaxPolyCurves doubleIntegrated; BuildCurves(doubleIntegrated, editorCurves, GetScalar(), minMaxState); doubleIntegrated.DoubleIntegrate(); return doubleIntegrated.FindMinMaxDoubleIntegrated(); } } template void MinMaxCurve::Transfer (TransferFunction& transfer) { transfer.Transfer (scalar, "scalar"); transfer.Transfer (editorCurves.max, "maxCurve"); transfer.Transfer (editorCurves.min, "minCurve"); TRANSFER (minMaxState); transfer.Align (); if (transfer.IsReading ()) isOptimizedCurve = BuildCurves(polyCurves, editorCurves, scalar, minMaxState); } INSTANTIATE_TEMPLATE_TRANSFER(MinMaxCurve) NS_RRP_END