From a4cab567b3a2968e8dcc48acfec90f44146bacec Mon Sep 17 00:00:00 2001 From: Michel Fedde Date: Sun, 28 Mar 2021 17:33:52 +0200 Subject: [PATCH] Implermented Interpolation for CVector --- SMCode/SM.Base/Animation/AnimationCurves.cs | 20 +++ .../SM.Base/Animation/InterpolationProcess.cs | 90 ++++++++++++ SMCode/SM.Base/SM.Base.csproj | 5 + SMCode/SM.Base/Types/CVector1.cs | 86 +++++------ SMCode/SM.Base/Types/CVector2.cs | 52 +++++-- SMCode/SM.Base/Types/CVector3.cs | 50 +++++-- SMCode/SM.Base/Types/CVector4.cs | 139 ++++++++++++++++++ SMCode/SM.Base/Types/CVectorBase.cs | 83 +++++++++++ SMCode/SM2D/Scene/ItemCollection.cs | 1 + SM_TEST/Program.cs | 16 +- 10 files changed, 463 insertions(+), 79 deletions(-) create mode 100644 SMCode/SM.Base/Animation/AnimationCurves.cs create mode 100644 SMCode/SM.Base/Animation/InterpolationProcess.cs create mode 100644 SMCode/SM.Base/Types/CVector4.cs create mode 100644 SMCode/SM.Base/Types/CVectorBase.cs diff --git a/SMCode/SM.Base/Animation/AnimationCurves.cs b/SMCode/SM.Base/Animation/AnimationCurves.cs new file mode 100644 index 0000000..19fe9d4 --- /dev/null +++ b/SMCode/SM.Base/Animation/AnimationCurves.cs @@ -0,0 +1,20 @@ +using OpenTK; + +namespace SM.Base.Animation +{ + /// + /// Preset Animation curves. + /// + public class AnimationCurves + { + /// + /// Linear Curve + /// + public static readonly BezierCurve Linear = new BezierCurve(Vector2.Zero, Vector2.One); + + /// + /// Smooth curve + /// + public static readonly BezierCurve Smooth = new BezierCurve(Vector2.Zero, new Vector2(.5f, 0), new Vector2(.5f, 1), Vector2.One); + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Animation/InterpolationProcess.cs b/SMCode/SM.Base/Animation/InterpolationProcess.cs new file mode 100644 index 0000000..83b6de8 --- /dev/null +++ b/SMCode/SM.Base/Animation/InterpolationProcess.cs @@ -0,0 +1,90 @@ +using System; +using OpenTK; +using SM.Base.Time; +using SM.Base.Types; +using SM.Base.Window; + +namespace SM.Base.Animation +{ + /// + /// A handle to control the interpolation process. + /// + public class InterpolationProcess : Timer + { + /// + /// The CVector object, that is interpolated. + /// + public CVectorBase TargetVector { get; set; } + + /// + /// From where the interpolation process started. + /// + public Vector4 From { get; } + /// + /// To where the interpolation is heading. + /// + public Vector4 To { get; } + /// + /// The direction towards the + /// + public Vector4 Direction { get; } + + /// + /// Gets/Sets the interpolation curve. + /// + public BezierCurve InterpolationCurve { get; set; } + + internal InterpolationProcess(CVectorBase targetVector, TimeSpan timeSpan, Vector4 from, Vector4 to, BezierCurve interpolationCurve) : base(timeSpan) + { + TargetVector = targetVector; + + From = from; + To = to; + InterpolationCurve = interpolationCurve; + + Direction = to - from; + } + + /// + /// Stops the interpolation process. + /// This keeps the state where the interpolation was. + /// + public new void Stop() + { + Stop(true); + } + + /// + /// Stops the interplation process. + /// + /// If true, it will not set the state to the state. + public void Stop(bool keepState) + { + if (Active && !keepState) SetTarget(To); + + base.Stop(); + + } + + private protected override void Ticking(UpdateContext context) + { + base.Ticking(context); + + float posInCurve = InterpolationCurve.CalculatePoint(ElapsedNormalized).Y; + Vector4 nextPos = From + (Direction * posInCurve); + SetTarget(nextPos); + } + + /// + protected override void Stopping(UpdateContext context) + { + base.Stopping(context); + SetTarget(To); + } + + private void SetTarget(Vector4 vec) + { + TargetVector.Set(vec.X, vec.Y, vec.Z, vec.W); + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/SM.Base.csproj b/SMCode/SM.Base/SM.Base.csproj index c2abcad..df0a4fa 100644 --- a/SMCode/SM.Base/SM.Base.csproj +++ b/SMCode/SM.Base/SM.Base.csproj @@ -48,6 +48,8 @@ + + @@ -63,6 +65,8 @@ + + @@ -139,5 +143,6 @@ + \ No newline at end of file diff --git a/SMCode/SM.Base/Types/CVector1.cs b/SMCode/SM.Base/Types/CVector1.cs index 2125112..1dcb6ba 100644 --- a/SMCode/SM.Base/Types/CVector1.cs +++ b/SMCode/SM.Base/Types/CVector1.cs @@ -1,6 +1,9 @@ #region usings using System; +using System.Runtime.InteropServices.WindowsRuntime; +using OpenTK; +using SM.Base.Animation; #endregion @@ -9,7 +12,7 @@ namespace SM.Base.Types /// /// A One-dimensional Vector (also known as ), in a class. /// - public class CVector1 + public class CVector1 : CVectorBase { /// /// Creates a class vector @@ -26,45 +29,18 @@ namespace SM.Base.Types public float X { get; set; } /// - /// The length/magnitute of the vector. + /// Interpolates the motion to the target. /// - public float Length => GetLength(); - - /// - /// Gets the square of the vector length (magnitude). - /// - /// - /// This property avoids the costly square root operation required by the Length property. This makes it more suitable - /// for comparisons. - /// - public float LengthSquared => GetLength(true); - - /// - /// This event triggers when a component changed. - /// - public event Action Changed; - - - /// - /// Get the length of the vector. - /// - /// If true, it will return the squared product. - /// - public float GetLength(bool squared = false) + /// How long the interpolation should take. + /// The value it should interpolate. + /// The curve how he interpolates. Preset values can be found under . Default: + /// A handle to control the interpolation process. + public InterpolationProcess Interpolate(TimeSpan duration, float to, BezierCurve? interpolationCurve = null) { - float length = GetLengthProcess(); - if (squared) return length; - return (float) Math.Sqrt(length); - } + InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to, 0, 0, 0), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear)); + process.Start(); - - /// - /// Normalizes the vector. - /// - public void Normalize() - { - float length = GetLength(); - NormalizationProcess(length); + return process; } /// @@ -76,6 +52,12 @@ namespace SM.Base.Types if (triggerChanged) TriggerChanged(); } + /// + public override void Set(params float[] parameters) + { + X = parameters[0]; + } + /// /// Adds the value to the components. /// @@ -85,20 +67,11 @@ namespace SM.Base.Types if (triggerChanged) TriggerChanged(); } - /// - /// Conversion into - /// - public static implicit operator float(CVector1 vector1) - { - return vector1.X; - } - /// /// Conversion from to One-dimensional Vector. /// /// - //public static implicit operator CVector1(float f) => new CVector1(f); - protected virtual float GetLengthProcess() + protected override float GetLengthProcess() { return X * X; } @@ -107,17 +80,16 @@ namespace SM.Base.Types /// Normalizes the vector. /// /// - protected virtual void NormalizationProcess(float length) + protected override void NormalizationProcess(float length) { X *= length; } - /// - /// This triggers the event. - /// - protected void TriggerChanged() + + /// + protected override Vector4 ConvertToVector4() { - Changed?.Invoke(); + return new Vector4(X, 0, 0, 0); } /// @@ -125,5 +97,13 @@ namespace SM.Base.Types { return X.ToString(); } + + /// + /// Conversion into + /// + public static implicit operator float(CVector1 vector1) + { + return vector1.X; + } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Types/CVector2.cs b/SMCode/SM.Base/Types/CVector2.cs index 6d1a8b1..521458b 100644 --- a/SMCode/SM.Base/Types/CVector2.cs +++ b/SMCode/SM.Base/Types/CVector2.cs @@ -1,6 +1,8 @@ #region usings +using System; using OpenTK; +using SM.Base.Animation; #endregion @@ -33,17 +35,23 @@ namespace SM.Base.Types /// public float Y { get; set; } - /// - protected override float GetLengthProcess() + /// + /// Interpolates the motion to the target. + /// + /// How long the interpolation should take. + /// The value it should interpolate. + /// The curve how he interpolates. + /// When creating a curve, its recommended the Y-component is always between 0 -> 1. But it could make cool effects if not... + /// Preset curves can be found under . + /// Default: + /// + /// A handle to control the interpolation process. + public InterpolationProcess Interpolate(TimeSpan duration, Vector2 to, BezierCurve? interpolationCurve = null) { - return base.GetLengthProcess() + Y * Y; - } + InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear)); + process.Start(); - /// - protected override void NormalizationProcess(float length) - { - base.NormalizationProcess(length); - Y *= length; + return process; } /// @@ -78,6 +86,13 @@ namespace SM.Base.Types base.Set(x, triggerChanged); } + /// + public override void Set(params float[] parameters) + { + base.Set(parameters); + Y = parameters[1]; + } + /// public override void Add(float uniform, bool triggerChanged = true) { @@ -107,6 +122,25 @@ namespace SM.Base.Types base.Add(x, triggerChanged); } + /// + protected override float GetLengthProcess() + { + return base.GetLengthProcess() + Y * Y; + } + + /// + protected override void NormalizationProcess(float length) + { + base.NormalizationProcess(length); + Y *= length; + } + + /// + protected override Vector4 ConvertToVector4() + { + return new Vector4(X,Y, 0, 0); + } + /// /// Converts to /// diff --git a/SMCode/SM.Base/Types/CVector3.cs b/SMCode/SM.Base/Types/CVector3.cs index 58b881e..3281510 100644 --- a/SMCode/SM.Base/Types/CVector3.cs +++ b/SMCode/SM.Base/Types/CVector3.cs @@ -1,6 +1,8 @@ #region usings +using System; using OpenTK; +using SM.Base.Animation; #endregion @@ -33,23 +35,26 @@ namespace SM.Base.Types /// public float Z { get; set; } - /// - protected override float GetLengthProcess() + /// + /// Interpolates the motion to the target. + /// + /// How long the interpolation should take. + /// The value it should interpolate. + /// The curve how he interpolates. Preset values can be found under . Default: + /// A handle to control the interpolation process. + public InterpolationProcess Interpolate(TimeSpan duration, Vector3 to, BezierCurve? interpolationCurve = null) { - return base.GetLengthProcess() + Z * Z; + InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to, 0), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear)); + process.Start(); + + return process; } - /// - protected override void NormalizationProcess(float length) - { - base.NormalizationProcess(length); - Z *= length; - } /// public override string ToString() { - return "{" + X + "; " + Y + "}"; + return "{" + X + "; " + Y + "; "+Z+"}"; } /// @@ -76,6 +81,13 @@ namespace SM.Base.Types Set(vector.X, vector.Y, vector.Z, triggerChanged); } + /// + public override void Set(params float[] parameters) + { + base.Set(parameters); + Z = parameters[2]; + } + /// public override void Add(float uniform, bool triggerChanged = true) { @@ -106,6 +118,24 @@ namespace SM.Base.Types base.Add(x, y, triggerChanged); } + /// + protected override float GetLengthProcess() + { + return base.GetLengthProcess() + Z * Z; + } + + /// + protected override void NormalizationProcess(float length) + { + base.NormalizationProcess(length); + Z *= length; + } + /// + protected override Vector4 ConvertToVector4() + { + return new Vector4(X, Y, Z, 0); + } + /// /// Converts to /// diff --git a/SMCode/SM.Base/Types/CVector4.cs b/SMCode/SM.Base/Types/CVector4.cs new file mode 100644 index 0000000..368e870 --- /dev/null +++ b/SMCode/SM.Base/Types/CVector4.cs @@ -0,0 +1,139 @@ +using System; +using System.Windows.Forms; +using OpenTK; +using SM.Base.Animation; + +namespace SM.Base.Types +{ + /// + public class CVector4 : CVector3 + { + /// + /// The W-component. + /// + public float W { get; set; } + + /// + public CVector4(float uniform) : base(uniform) + { + W = uniform; + } + + /// + public CVector4(float x, float y, float z, float w) : base(x, y, z) + { + W = w; + } + + /// + /// Interpolates the motion to the target. + /// + /// How long the interpolation should take. + /// The value it should interpolate. + /// The curve how he interpolates. Preset values can be found under . Default: + /// A handle to control the interpolation process. + public InterpolationProcess Interpolate(TimeSpan duration, Vector4 to, BezierCurve? interpolationCurve = null) + { + InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), to, interpolationCurve.GetValueOrDefault(AnimationCurves.Linear)); + process.Start(); + + return process; + } + + /// + public override void Set(float uniform, bool triggerChanged = true) + { + W = uniform; + base.Set(uniform, triggerChanged); + } + + + /// + /// Sets the a own value to each component. + /// + public void Set(float x, float y, float z, float w, bool triggerChanged = true) + { + W = w; + base.Set(x, y, z, triggerChanged); + } + + /// + /// Sets each component to the counter-part. + /// + public void Set(Vector4 vector, bool triggerChanged = true) + { + Set(vector.X, vector.Y, vector.Z, vector.W, triggerChanged); + } + + /// + public override void Set(params float[] parameters) + { + base.Set(parameters); + W = parameters[3]; + } + + /// + public override void Add(float uniform, bool triggerChanged = true) + { + W += uniform; + base.Add(uniform, triggerChanged); + } + /// + /// Adds a to the CVector. + /// + /// + /// If false, the event Changed doesn't gets triggered + public void Add(Vector4 vector, bool triggerChanged = true) + { + Add(vector.X, vector.Y, vector.Z, vector.W, triggerChanged); + } + + /// + /// Adds the values to the CVector. + /// + /// + /// + /// + /// + /// If false, the event Changed doesn't gets triggered + public void Add(float x, float y, float z, float w, bool triggerChanged = true) + { + W = w; + base.Add(x, y, z, triggerChanged); + } + /// + public override string ToString() + { + return "{" + X + "; " + Y + "; " + Z + "; " + W + "}"; + } + + /// + protected override float GetLengthProcess() + { + return base.GetLengthProcess() + W * W; + } + + /// + protected override void NormalizationProcess(float length) + { + base.NormalizationProcess(length); + W *= length; + } + + /// + protected override Vector4 ConvertToVector4() + { + return new Vector4(X, Y, Z, W); + } + + /// + /// Converts a into a . + /// + public static implicit operator Vector4(CVector4 vector) => new Vector4(vector.X, vector.Y, vector.Z, vector.W); + /// + /// Converts a into a . + /// + + public static implicit operator CVector4(Vector4 vector) => new CVector4(vector.X, vector.Y, vector.Z, vector.W); + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Types/CVectorBase.cs b/SMCode/SM.Base/Types/CVectorBase.cs new file mode 100644 index 0000000..e740a39 --- /dev/null +++ b/SMCode/SM.Base/Types/CVectorBase.cs @@ -0,0 +1,83 @@ +using System; +using OpenTK; + +namespace SM.Base.Types +{ + /// + /// Basis for the CVector classes + /// + public abstract class CVectorBase + { + /// + /// This event triggers when a component changed. + /// + public event Action Changed; + + /// + /// The length/magnitute of the vector. + /// + public float Length => GetLength(); + + /// + /// Gets the square of the vector length (magnitude). + /// + /// + /// This property avoids the costly square root operation required by the Length property. This makes it more suitable + /// for comparisons. + /// + public float LengthSquared => GetLength(true); + + /// + /// Get the length of the vector. + /// + /// If true, it will return the squared product. + /// + public float GetLength(bool squared = false) + { + float length = GetLengthProcess(); + if (squared) return length; + return (float)Math.Sqrt(length); + } + + /// + /// Normalizes the vector. + /// + public void Normalize() + { + float length = GetLength(); + NormalizationProcess(length); + } + + /// + /// Sets the values of the vector, by providing the values over an array. + /// + /// + public abstract void Set(params float[] parameters); + + /// + /// This triggers the event. + /// + protected void TriggerChanged() + { + Changed?.Invoke(); + } + + /// + /// Conversion from to One-dimensional Vector. + /// + /// + protected abstract float GetLengthProcess(); + + /// + /// Normalizes the vector. + /// + /// + protected abstract void NormalizationProcess(float length); + + /// + /// Converts the vector to a + /// + /// + protected abstract Vector4 ConvertToVector4(); + } +} \ No newline at end of file diff --git a/SMCode/SM2D/Scene/ItemCollection.cs b/SMCode/SM2D/Scene/ItemCollection.cs index ff86581..3ba51fb 100644 --- a/SMCode/SM2D/Scene/ItemCollection.cs +++ b/SMCode/SM2D/Scene/ItemCollection.cs @@ -19,6 +19,7 @@ namespace SM2D.Scene Transform.Size = new CVector2(1); } + /// public override void Draw(DrawContext context) { this.Sort(Comparitor); diff --git a/SM_TEST/Program.cs b/SM_TEST/Program.cs index b3a325e..a191b8c 100644 --- a/SM_TEST/Program.cs +++ b/SM_TEST/Program.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using OpenTK; +using SM.Base.Animation; using SM.Base.Controls; using SM.Base.Time; using SM.Base.Window; @@ -17,6 +18,8 @@ namespace SM_TEST private static GLWindow window; private static PolyLine line; private static DrawParticles particles; + + private static InterpolationProcess interpolation; static void Main(string[] args) { window = new GLWindow(1280, 720, "0ms", WindowFlags.Window, VSyncMode.Off); @@ -25,12 +28,9 @@ namespace SM_TEST window.SetScene(scene = new Scene()); - particles = new DrawParticles(TimeSpan.FromSeconds(5)) - { - MaxSpeed = 50, - }; - particles.Transform.Size.Set(20); - scene.Objects.Add(particles); + DrawObject2D testObj = new DrawObject2D(); + interpolation = testObj.Transform.Position.Interpolate(TimeSpan.FromSeconds(5), new Vector2(300), new BezierCurve(Vector2.Zero,new Vector2(0.43f, 0), new Vector2(.5f, 1.5f), Vector2.One)); + scene.Objects.Add(testObj); window.UpdateFrame += WindowOnUpdateFrame; window.RenderFrame += Window_RenderFrame; @@ -47,7 +47,9 @@ namespace SM_TEST private static void WindowOnUpdateFrame(object sender, FrameEventArgs e) { if (Mouse.LeftClick) - particles.Trigger(); + interpolation.Stop(); + if (Mouse.RightClick) + interpolation.Stop(false); } } } \ No newline at end of file