Example #1
0
        protected override void ProcessImpl(float[] buffer, int offset, int count)
        {
            int numSamples = count / 2;

            if (Duration == 0.0)
            {
                return;
            }

            double step = 1.0 / SampleRate;

            for (int i = 0; i < numSamples; i++)
            {
                float r = (float)(time / Duration);
                // FadeIn
                const float fadeIn = 0.08f;
                if (r < fadeIn)
                {
                    r = 1.0f - r / fadeIn;
                }
                else
                {
                    r = Curve.Sample((r - fadeIn) / (1.0f - fadeIn));
                }
                float sampleGain = 1.0f - Amount * (1.0f - r) * Mix;
                buffer[offset + i * 2 + 0] *= sampleGain;
                buffer[offset + i * 2 + 1] *= sampleGain;

                time += step;
                if (time > Duration)
                {
                    time = 0;
                }
            }
        }
Example #2
0
        protected override void ProcessImpl(float[] buffer, int offset, int count)
        {
            int numSamples = count / 2;

            for (int i = 0; i < numSamples; i++)
            {
                float f = MathL.Abs(2.0f * ((float)m_currentSample / m_length) - 1.0f);
                f = easing.Sample(f);
                float freq = fmin + (fmax - fmin) * f;
                filter.SetLowPass(q, freq);

                float[] s = { buffer[i * 2], buffer[i * 2 + 1] };
                filter.Process(s, 0, 2);

                // Apply slight mixing
                float addMix = 0.85f;
                //buffer[i * 2 + 0] = buffer[i * 2 + 0] * addMix + s[0] * (1.0f - addMix);
                //buffer[i * 2 + 1] = buffer[i * 2 + 1] * addMix + s[1] * (1.0f - addMix);

                buffer[i * 2 + 0] = MathL.Lerp(buffer[i * 2 + 0], s[0], Mix * addMix);
                buffer[i * 2 + 1] = MathL.Lerp(buffer[i * 2 + 1], s[1], Mix * addMix);

                m_currentSample++;
                m_currentSample %= m_length;
            }
        }
Example #3
0
        protected override void ProcessImpl(Span <float> buffer)
        {
            int numSamples = buffer.Length / 2;

            for (int i = 0; i < numSamples; i++)
            {
                float f = MathL.Abs(2.0f * ((float)m_currentSample / m_length) - 1.0f);
                f = easing.Sample(f);
                float freq = fmin + (fmax - fmin) * f;
                filter.SetLowPass(q, freq);

                float[] s = { buffer[i * 2], buffer[i * 2 + 1] };
                filter.Process(s);

                float addMix = 0.85f;
                buffer[i * 2 + 0] = MathL.Lerp(buffer[i * 2 + 0], s[0], Mix * addMix);
                buffer[i * 2 + 1] = MathL.Lerp(buffer[i * 2 + 1], s[1], Mix * addMix);

                m_currentSample++;
                m_currentSample %= m_length;
            }
        }
Example #4
0
 protected override float Interp(float min, float max, float alpha) => m_curve.Sample(alpha) * (max - min) + min;
Example #5
0
 protected override int Interp(int min, int max, float alpha) => (int)(m_curve.Sample(alpha) * (max - min)) + min;
        internal void Interpolate(
            ActorPatch finalFrame,
            string animationName,
            float duration,
            float[] curve,
            bool enabled)
        {
            // Ensure duration is in range [0...n].
            duration = Math.Max(0, duration);

            const int FPS      = 10;
            float     timeStep = duration / FPS;

            // If the curve is malformed, fall back to linear.
            if (curve.Length != 4)
            {
                curve = new float[] { 0, 0, 1, 1 };
            }

            // Are we patching the transform?
            bool animateTransform = finalFrame.Transform != null && finalFrame.Transform.Local != null && finalFrame.Transform.Local.IsPatched();
            var  finalTransform   = finalFrame.Transform.Local;

            // What parts of the transform are we animating?
            bool animatePosition = animateTransform && finalTransform.Position != null && finalTransform.Position.IsPatched();
            bool animateRotation = animateTransform && finalTransform.Rotation != null && finalTransform.Rotation.IsPatched();
            bool animateScale    = animateTransform && finalTransform.Scale != null && finalTransform.Scale.IsPatched();

            // Ensure we have a well-formed rotation quaternion.
            for (; animateRotation;)
            {
                var  rotation         = finalTransform.Rotation;
                bool hasAllComponents =
                    rotation.X.HasValue &&
                    rotation.Y.HasValue &&
                    rotation.Z.HasValue &&
                    rotation.W.HasValue;

                // If quaternion is incomplete, fall back to the identity.
                if (!hasAllComponents)
                {
                    finalTransform.Rotation = new QuaternionPatch(Quaternion.identity);
                    break;
                }

                // Ensure the quaternion is normalized.
                var lengthSquared =
                    (rotation.X.Value * rotation.X.Value) +
                    (rotation.Y.Value * rotation.Y.Value) +
                    (rotation.Z.Value * rotation.Z.Value) +
                    (rotation.W.Value * rotation.W.Value);
                if (lengthSquared == 0)
                {
                    // If the quaternion is length zero, fall back to the identity.
                    finalTransform.Rotation = new QuaternionPatch(Quaternion.identity);
                    break;
                }
                else if (lengthSquared != 1.0f)
                {
                    // If the quaternion length is not 1, normalize it.
                    var inverseLength = 1.0f / Mathf.Sqrt(lengthSquared);
                    rotation.X *= inverseLength;
                    rotation.Y *= inverseLength;
                    rotation.Z *= inverseLength;
                    rotation.W *= inverseLength;
                }
                break;
            }

            // Create the sampler to calculate ease curve values.
            var sampler = new CubicBezier(curve[0], curve[1], curve[2], curve[3]);

            var keyframes = new List <MWAnimationKeyframe>();

            // Generate keyframes
            float currTime = 0;

            do
            {
                var keyframe = NewKeyframe(currTime);
                var unitTime = duration > 0 ? currTime / duration : 1;
                BuildKeyframe(keyframe, unitTime);
                keyframes.Add(keyframe);
                currTime += timeStep;
            }while (currTime <= duration && timeStep > 0);

            // Final frame (if needed)
            if (currTime - duration > 0)
            {
                var keyframe = NewKeyframe(duration);
                BuildKeyframe(keyframe, 1);
                keyframes.Add(keyframe);
            }

            // Create and optionally start the animation.
            CreateAnimation(
                animationName,
                keyframes,
                events: null,
                wrapMode: MWAnimationWrapMode.Once,
                initialState: new MWSetAnimationStateOptions {
                Enabled = enabled
            },
                isInternal: true,
                managed: false,
                onCreatedCallback: null);

            bool LerpFloat(out float dest, float start, float?end, float t)
            {
                if (end.HasValue)
                {
                    dest = Mathf.LerpUnclamped(start, end.Value, t);
                    return(true);
                }
                dest = 0;
                return(false);
            }

            bool SlerpQuaternion(out Quaternion dest, Quaternion start, QuaternionPatch end, float t)
            {
                if (end != null)
                {
                    dest = Quaternion.SlerpUnclamped(start, new Quaternion(end.X.Value, end.Y.Value, end.Z.Value, end.W.Value), t);
                    return(true);
                }
                dest = Quaternion.identity;
                return(false);
            }

            void BuildKeyframePosition(MWAnimationKeyframe keyframe, float t)
            {
                float value;

                if (LerpFloat(out value, transform.localPosition.x, finalTransform.Position.X, t))
                {
                    keyframe.Value.Transform.Local.Position.X = value;
                }
                if (LerpFloat(out value, transform.localPosition.y, finalTransform.Position.Y, t))
                {
                    keyframe.Value.Transform.Local.Position.Y = value;
                }
                if (LerpFloat(out value, transform.localPosition.z, finalTransform.Position.Z, t))
                {
                    keyframe.Value.Transform.Local.Position.Z = value;
                }
            }

            void BuildKeyframeScale(MWAnimationKeyframe keyframe, float t)
            {
                float value;

                if (LerpFloat(out value, transform.localScale.x, finalTransform.Scale.X, t))
                {
                    keyframe.Value.Transform.Local.Scale.X = value;
                }
                if (LerpFloat(out value, transform.localScale.y, finalTransform.Scale.Y, t))
                {
                    keyframe.Value.Transform.Local.Scale.Y = value;
                }
                if (LerpFloat(out value, transform.localScale.z, finalTransform.Scale.Z, t))
                {
                    keyframe.Value.Transform.Local.Scale.Z = value;
                }
            }

            void BuildKeyframeRotation(MWAnimationKeyframe keyframe, float t)
            {
                Quaternion value;

                if (SlerpQuaternion(out value, transform.localRotation, finalTransform.Rotation, t))
                {
                    keyframe.Value.Transform.Local.Rotation = new QuaternionPatch(value);
                }
            }

            void BuildKeyframe(MWAnimationKeyframe keyframe, float unitTime)
            {
                float curveTime = sampler.Sample(unitTime);

                if (animatePosition)
                {
                    BuildKeyframePosition(keyframe, curveTime);
                }
                if (animateRotation)
                {
                    BuildKeyframeRotation(keyframe, curveTime);
                }
                if (animateScale)
                {
                    BuildKeyframeScale(keyframe, curveTime);
                }
            }

            MWAnimationKeyframe NewKeyframe(float time)
            {
                var keyframe = new MWAnimationKeyframe
                {
                    Time  = time,
                    Value = new ActorPatch()
                };

                if (animateTransform)
                {
                    keyframe.Value.Transform = new ActorTransformPatch()
                    {
                        Local = new ScaledTransformPatch()
                    };
                }
                if (animatePosition)
                {
                    keyframe.Value.Transform.Local.Position = new Vector3Patch();
                }
                if (animateRotation)
                {
                    keyframe.Value.Transform.Local.Rotation = new QuaternionPatch();
                }
                if (animateScale)
                {
                    keyframe.Value.Transform.Local.Scale = new Vector3Patch();
                }
                return(keyframe);
            }
        }
Example #7
0
        /// <summary>
        /// Computes the maximum squared distance from a point to the curve using the current parameterization.
        /// </summary>
        protected FLOAT FindMaxSquaredError(int first, int last, CubicBezier curve, out int split)
        {
            List<VECTOR> pts = _pts;
            List<FLOAT> u = _u;
            int s = (last - first + 1) / 2;
            int nPts = last - first + 1;
            FLOAT max = 0;
            for (int i = 1; i < nPts; i++)
            {
                VECTOR v0 = pts[first + i];
                VECTOR v1 = curve.Sample(u[i]);
                FLOAT d = VectorHelper.DistanceSquared(v0, v1);
                if (d > max)
                {
                    max = d;
                    s = i;
                }
            }

            // split at point of maximum error
            split = s + first;
            if (split <= first)
                split = first + 1;
            if (split >= last)
                split = last - 1;
            return max;
        }
Example #8
0
 /// <summary>
 /// Attempts to find a slightly better parameterization for u on the given curve.
 /// </summary>
 protected void Reparameterize(int first, int last, CubicBezier curve)
 {
     List<VECTOR> pts = _pts;
     List<FLOAT> u = _u;
     int nPts = last - first;
     for (int i = 1; i < nPts; i++)
     {
         VECTOR p = pts[first + i];
         FLOAT t = u[i];
         FLOAT ti = 1 - t;
         // Control vertices for Q'
         VECTOR qp0 = (curve.p1 - curve.p0) * 3;
         VECTOR qp1 = (curve.p2 - curve.p1) * 3;
         VECTOR qp2 = (curve.p3 - curve.p2) * 3;
         // Control vertices for Q''
         VECTOR qpp0 = (qp1 - qp0) * 2;
         VECTOR qpp1 = (qp2 - qp1) * 2;
         // Evaluate Q(t), Q'(t), and Q''(t)
         VECTOR p0 = curve.Sample(t);
         VECTOR p1 = ((ti * ti) * qp0) + ((2 * ti * t) * qp1) + ((t * t) * qp2);
         VECTOR p2 = (ti * qpp0) + (t * qpp1);
         // these are the actual fitting calculations using http://en.wikipedia.org/wiki/Newton%27s_method
         // We can't just use .X and .Y because Unity uses lower-case "x" and "y".
         FLOAT num = ((VectorHelper.GetX(p0) - VectorHelper.GetX(p)) * VectorHelper.GetX(p1)) + ((VectorHelper.GetY(p0) - VectorHelper.GetY(p)) * VectorHelper.GetY(p1));
         FLOAT den = (VectorHelper.GetX(p1) * VectorHelper.GetX(p1)) + (VectorHelper.GetY(p1) * VectorHelper.GetY(p1)) + ((VectorHelper.GetX(p0) - VectorHelper.GetX(p)) * VectorHelper.GetX(p2)) + ((VectorHelper.GetY(p0) - VectorHelper.GetY(p)) * VectorHelper.GetY(p2));
         FLOAT newU = t - num / den;
         if (Math.Abs(den) > EPSILON && newU >= 0 && newU <= 1)
             u[i] = newU;
     }
 }
Example #9
0
 public EffectParamF(float a, float b, CubicBezier curve)
     : base(a, b, (x, y, t) => curve.Sample(t) * (y - x) + x)
 {
 }
Example #10
0
 public EffectParamI(int a, int b, CubicBezier curve)
     : base(a, b, (x, y, t) => (int)(curve.Sample(t) * (y - x)) + x)
 {
 }