diff options
Diffstat (limited to 'Runtime/Graphics/ParticleSystem/ParticleSystemCurves.h')
-rw-r--r-- | Runtime/Graphics/ParticleSystem/ParticleSystemCurves.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/Runtime/Graphics/ParticleSystem/ParticleSystemCurves.h b/Runtime/Graphics/ParticleSystem/ParticleSystemCurves.h new file mode 100644 index 0000000..5d59eb2 --- /dev/null +++ b/Runtime/Graphics/ParticleSystem/ParticleSystemCurves.h @@ -0,0 +1,187 @@ +#ifndef SHURIKENCURVES_H +#define SHURIKENCURVES_H + +#include "ParticleSystemParticle.h" +#include "PolynomialCurve.h" +#include "Runtime/Math/AnimationCurve.h" + + +struct MinMaxCurve; + +// Some profile numbers from a run with 250,000 particles evaluating 3 velocity properties each on Intel i7-2600 CPU @ 3.4 GHz +// Scalar: 4.6 ms +// Optimized curve: 7.2 ms +// Random between 2 scalars: 9.5 ms +// Random between 2 curves: 9.5 ms +// Non-optimized curve: 10.0 ms +// Random between 2 non-optimized curves: 12.0 ms + +enum ParticleSystemCurveEvalMode +{ + kEMScalar, + kEMOptimized, + kEMOptimizedMinMax, + kEMSlow, +}; + +enum MinMaxCurveState +{ + kMMCScalar = 0, + kMMCCurve = 1, + kMMCTwoCurves = 2, + kMMCTwoConstants = 3 +}; + +struct MinMaxOptimizedPolyCurves +{ + void Integrate(); + void DoubleIntegrate(); + Vector2f FindMinMaxIntegrated(); + Vector2f FindMinMaxDoubleIntegrated(); + + OptimizedPolynomialCurve max; + OptimizedPolynomialCurve min; +}; + +inline float EvaluateIntegrated (const MinMaxOptimizedPolyCurves& curves, float t, float factor) +{ + const float v0 = curves.min.EvaluateIntegrated (t); + const float v1 = curves.max.EvaluateIntegrated (t); + return Lerp (v0, v1, factor); +} + +inline float EvaluateDoubleIntegrated (const MinMaxOptimizedPolyCurves& curves, float t, float factor) +{ + const float v0 = curves.min.EvaluateDoubleIntegrated (t); + const float v1 = curves.max.EvaluateDoubleIntegrated (t); + return Lerp (v0, v1, factor); +} + +struct MinMaxPolyCurves +{ + void Integrate(); + void DoubleIntegrate(); + Vector2f FindMinMaxIntegrated(); + Vector2f FindMinMaxDoubleIntegrated(); + + PolynomialCurve max; + PolynomialCurve min; +}; + +inline float EvaluateIntegrated (const MinMaxPolyCurves& curves, float t, float factor) +{ + const float v0 = curves.min.EvaluateIntegrated (t); + const float v1 = curves.max.EvaluateIntegrated (t); + return Lerp (v0, v1, factor); +} + +inline float EvaluateDoubleIntegrated (const MinMaxPolyCurves& curves, float t, float factor) +{ + const float v0 = curves.min.EvaluateDoubleIntegrated (t); + const float v1 = curves.max.EvaluateDoubleIntegrated (t); + return Lerp (v0, v1, factor); +} + +struct MinMaxAnimationCurves +{ + bool SupportsProcedural (); + + AnimationCurve max; + AnimationCurve min; +}; + +bool BuildCurves (MinMaxOptimizedPolyCurves& polyCurves, const MinMaxAnimationCurves& editorCurves, float scalar, short minMaxState); +void BuildCurves (MinMaxPolyCurves& polyCurves, const MinMaxAnimationCurves& editorCurves, float scalar, short minMaxState); +bool CurvesSupportProcedural (const MinMaxAnimationCurves& editorCurves, short minMaxState); + +struct MinMaxCurve +{ + MinMaxOptimizedPolyCurves polyCurves; +private: + float scalar; // Since scalar is baked into the optimized curve we use the setter function to modify it. + +public: + short minMaxState; // see enum MinMaxCurveState + bool isOptimizedCurve; + + MinMaxAnimationCurves editorCurves; + + MinMaxCurve (); + + inline float GetScalar() const { return scalar; } + inline void SetScalar(float value) { scalar = value; BuildCurves(polyCurves, editorCurves, scalar, minMaxState); } + + bool IsOptimized () const { return isOptimizedCurve; } + bool UsesMinMax () const { return (minMaxState == kMMCTwoCurves) || (minMaxState == kMMCTwoConstants); } + + DEFINE_GET_TYPESTRING (MinMaxCurve) + + template<class TransferFunction> + void Transfer (TransferFunction& transfer); + + Vector2f FindMinMax() const; + Vector2f FindMinMaxIntegrated() const; + Vector2f FindMinMaxDoubleIntegrated() const; +}; + +inline float EvaluateSlow (const MinMaxCurve& curve, float t, float factor) +{ + const float v = curve.editorCurves.max.Evaluate(t) * curve.GetScalar (); + if (curve.minMaxState == kMMCTwoCurves) + return Lerp (curve.editorCurves.min.Evaluate(t) * curve.GetScalar (), v, factor); + else + return v; +} + +template<ParticleSystemCurveEvalMode mode> +inline float Evaluate (const MinMaxCurve& curve, float t, float factor = 1.0F) +{ + if(mode == kEMScalar) + { + return curve.GetScalar(); + } + if(mode == kEMOptimized) + { + DebugAssert(curve.isOptimizedCurve); + return curve.polyCurves.max.Evaluate (t); + } + else if (mode == kEMOptimizedMinMax) + { + DebugAssert(curve.isOptimizedCurve); + const float v0 = curve.polyCurves.min.Evaluate (t); + const float v1 = curve.polyCurves.max.Evaluate (t); + return Lerp (v0, v1, factor); + } + else if (mode == kEMSlow) + { + return EvaluateSlow (curve, t, factor); + } +} + +inline float Evaluate (const MinMaxCurve& curve, float t, float randomValue = 1.0F) +{ + if (curve.minMaxState == kMMCScalar) + return curve.GetScalar (); + + if (curve.minMaxState == kMMCTwoConstants) + return Lerp ( curve.editorCurves.min.GetKey(0).value * curve.GetScalar (), + curve.editorCurves.max.GetKey(0).value * curve.GetScalar (), randomValue); + + DebugAssert(t <= 1.0F && t >= 0.0F); + if (curve.isOptimizedCurve) + return Evaluate<kEMOptimizedMinMax> (curve, t, randomValue); + else + return Evaluate<kEMSlow> (curve, t, randomValue); +} + +struct DualMinMax3DPolyCurves +{ + MinMaxOptimizedPolyCurves optX; + MinMaxOptimizedPolyCurves optY; + MinMaxOptimizedPolyCurves optZ; + MinMaxPolyCurves x; + MinMaxPolyCurves y; + MinMaxPolyCurves z; +}; + +#endif // SHURIKENCURVES_H |