Implermented Interpolation for CVector

This commit is contained in:
Michel Fedde 2021-03-28 17:33:52 +02:00
parent b45a10b676
commit a4cab567b3
10 changed files with 463 additions and 79 deletions

View file

@ -0,0 +1,20 @@
using OpenTK;
namespace SM.Base.Animation
{
/// <summary>
/// Preset Animation curves.
/// </summary>
public class AnimationCurves
{
/// <summary>
/// Linear Curve
/// </summary>
public static readonly BezierCurve Linear = new BezierCurve(Vector2.Zero, Vector2.One);
/// <summary>
/// Smooth curve
/// </summary>
public static readonly BezierCurve Smooth = new BezierCurve(Vector2.Zero, new Vector2(.5f, 0), new Vector2(.5f, 1), Vector2.One);
}
}

View file

@ -0,0 +1,90 @@
using System;
using OpenTK;
using SM.Base.Time;
using SM.Base.Types;
using SM.Base.Window;
namespace SM.Base.Animation
{
/// <summary>
/// A handle to control the interpolation process.
/// </summary>
public class InterpolationProcess : Timer
{
/// <summary>
/// The CVector object, that is interpolated.
/// </summary>
public CVectorBase TargetVector { get; set; }
/// <summary>
/// From where the interpolation process started.
/// </summary>
public Vector4 From { get; }
/// <summary>
/// To where the interpolation is heading.
/// </summary>
public Vector4 To { get; }
/// <summary>
/// The direction towards the <see cref="To"/>
/// </summary>
public Vector4 Direction { get; }
/// <summary>
/// Gets/Sets the interpolation curve.
/// </summary>
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;
}
/// <summary>
/// Stops the interpolation process.
/// <para>This keeps the state where the interpolation was.</para>
/// </summary>
public new void Stop()
{
Stop(true);
}
/// <summary>
/// Stops the interplation process.
/// </summary>
/// <param name="keepState">If true, it will not set the state to the <see cref="To"/> state.</param>
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);
}
/// <inheritdoc />
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);
}
}
}

View file

@ -48,6 +48,8 @@
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Animation\AnimationCurves.cs" />
<Compile Include="Animation\InterpolationProcess.cs" />
<Compile Include="Controls\Keyboard.cs" /> <Compile Include="Controls\Keyboard.cs" />
<Compile Include="Controls\Mouse.cs" /> <Compile Include="Controls\Mouse.cs" />
<Compile Include="Drawing\DrawingBasis.cs" /> <Compile Include="Drawing\DrawingBasis.cs" />
@ -63,6 +65,8 @@
<Compile Include="Drawing\Particles\ParticleStruct.cs" /> <Compile Include="Drawing\Particles\ParticleStruct.cs" />
<Compile Include="Drawing\Particles\ParticleDrawingBasis.cs" /> <Compile Include="Drawing\Particles\ParticleDrawingBasis.cs" />
<Compile Include="Shaders\SimpleShader.cs" /> <Compile Include="Shaders\SimpleShader.cs" />
<Compile Include="Types\CVector4.cs" />
<Compile Include="Types\CVectorBase.cs" />
<Compile Include="Utility\IInitializable.cs" /> <Compile Include="Utility\IInitializable.cs" />
<Compile Include="Utility\Ray.cs" /> <Compile Include="Utility\Ray.cs" />
<Compile Include="Utility\Util.cs" /> <Compile Include="Utility\Util.cs" />
@ -139,5 +143,6 @@
<EmbeddedResource Include="Shaders\Extensions\fragment\textureGamma.glsl" /> <EmbeddedResource Include="Shaders\Extensions\fragment\textureGamma.glsl" />
<EmbeddedResource Include="Shaders\Extensions\fragment\noise.glsl" /> <EmbeddedResource Include="Shaders\Extensions\fragment\noise.glsl" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -1,6 +1,9 @@
#region usings #region usings
using System; using System;
using System.Runtime.InteropServices.WindowsRuntime;
using OpenTK;
using SM.Base.Animation;
#endregion #endregion
@ -9,7 +12,7 @@ namespace SM.Base.Types
/// <summary> /// <summary>
/// A One-dimensional Vector (also known as <see cref="float" />), in a class. /// A One-dimensional Vector (also known as <see cref="float" />), in a class.
/// </summary> /// </summary>
public class CVector1 public class CVector1 : CVectorBase
{ {
/// <summary> /// <summary>
/// Creates a class vector /// Creates a class vector
@ -26,45 +29,18 @@ namespace SM.Base.Types
public float X { get; set; } public float X { get; set; }
/// <summary> /// <summary>
/// The length/magnitute of the vector. /// Interpolates the motion to the target.
/// </summary> /// </summary>
public float Length => GetLength(); /// <param name="duration">How long the interpolation should take.</param>
/// <param name="to">The value it should interpolate.</param>
/// <summary> /// <param name="interpolationCurve">The curve how he interpolates. Preset values can be found under <see cref="AnimationCurves"/>. Default: <see cref="AnimationCurves.Linear"/></param>
/// Gets the square of the vector length (magnitude). /// <returns>A handle to control the interpolation process.</returns>
/// </summary> public InterpolationProcess Interpolate(TimeSpan duration, float to, BezierCurve? interpolationCurve = null)
/// <remarks>
/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
/// for comparisons.
/// </remarks>
public float LengthSquared => GetLength(true);
/// <summary>
/// This event triggers when a component changed.
/// </summary>
public event Action Changed;
/// <summary>
/// Get the length of the vector.
/// </summary>
/// <param name="squared">If true, it will return the squared product.</param>
/// <returns></returns>
public float GetLength(bool squared = false)
{ {
float length = GetLengthProcess(); InterpolationProcess process = new InterpolationProcess(this, duration, ConvertToVector4(), new Vector4(to, 0, 0, 0), interpolationCurve.GetValueOrDefault(AnimationCurves.Linear));
if (squared) return length; process.Start();
return (float) Math.Sqrt(length);
}
return process;
/// <summary>
/// Normalizes the vector.
/// </summary>
public void Normalize()
{
float length = GetLength();
NormalizationProcess(length);
} }
/// <summary> /// <summary>
@ -76,6 +52,12 @@ namespace SM.Base.Types
if (triggerChanged) TriggerChanged(); if (triggerChanged) TriggerChanged();
} }
/// <inheritdoc />
public override void Set(params float[] parameters)
{
X = parameters[0];
}
/// <summary> /// <summary>
/// Adds the value to the components. /// Adds the value to the components.
/// </summary> /// </summary>
@ -85,20 +67,11 @@ namespace SM.Base.Types
if (triggerChanged) TriggerChanged(); if (triggerChanged) TriggerChanged();
} }
/// <summary>
/// Conversion into <see cref="float" />
/// </summary>
public static implicit operator float(CVector1 vector1)
{
return vector1.X;
}
/// <summary> /// <summary>
/// Conversion from <see cref="float" /> to One-dimensional Vector. /// Conversion from <see cref="float" /> to One-dimensional Vector.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
//public static implicit operator CVector1(float f) => new CVector1(f); protected override float GetLengthProcess()
protected virtual float GetLengthProcess()
{ {
return X * X; return X * X;
} }
@ -107,17 +80,16 @@ namespace SM.Base.Types
/// Normalizes the vector. /// Normalizes the vector.
/// </summary> /// </summary>
/// <param name="length"></param> /// <param name="length"></param>
protected virtual void NormalizationProcess(float length) protected override void NormalizationProcess(float length)
{ {
X *= length; X *= length;
} }
/// <summary>
/// This triggers the <see cref="Changed"/> event. /// <inheritdoc />
/// </summary> protected override Vector4 ConvertToVector4()
protected void TriggerChanged()
{ {
Changed?.Invoke(); return new Vector4(X, 0, 0, 0);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -125,5 +97,13 @@ namespace SM.Base.Types
{ {
return X.ToString(); return X.ToString();
} }
/// <summary>
/// Conversion into <see cref="float" />
/// </summary>
public static implicit operator float(CVector1 vector1)
{
return vector1.X;
}
} }
} }

View file

@ -1,6 +1,8 @@
#region usings #region usings
using System;
using OpenTK; using OpenTK;
using SM.Base.Animation;
#endregion #endregion
@ -33,17 +35,23 @@ namespace SM.Base.Types
/// </summary> /// </summary>
public float Y { get; set; } public float Y { get; set; }
/// <inheritdoc /> /// <summary>
protected override float GetLengthProcess() /// Interpolates the motion to the target.
/// </summary>
/// <param name="duration">How long the interpolation should take.</param>
/// <param name="to">The value it should interpolate.</param>
/// <param name="interpolationCurve">The curve how he interpolates.
/// <para>When creating a curve, its recommended the Y-component is always between 0 -> 1. But it could make cool effects if not...</para>
/// <para>Preset curves can be found under <see cref="AnimationCurves"/>.</para>
/// <para>Default: <see cref="AnimationCurves.Linear"/></para>
/// </param>
/// <returns>A handle to control the interpolation process.</returns>
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();
/// <inheritdoc /> return process;
protected override void NormalizationProcess(float length)
{
base.NormalizationProcess(length);
Y *= length;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -78,6 +86,13 @@ namespace SM.Base.Types
base.Set(x, triggerChanged); base.Set(x, triggerChanged);
} }
/// <inheritdoc />
public override void Set(params float[] parameters)
{
base.Set(parameters);
Y = parameters[1];
}
/// <inheritdoc /> /// <inheritdoc />
public override void Add(float uniform, bool triggerChanged = true) public override void Add(float uniform, bool triggerChanged = true)
{ {
@ -107,6 +122,25 @@ namespace SM.Base.Types
base.Add(x, triggerChanged); base.Add(x, triggerChanged);
} }
/// <inheritdoc />
protected override float GetLengthProcess()
{
return base.GetLengthProcess() + Y * Y;
}
/// <inheritdoc />
protected override void NormalizationProcess(float length)
{
base.NormalizationProcess(length);
Y *= length;
}
/// <inheritdoc />
protected override Vector4 ConvertToVector4()
{
return new Vector4(X,Y, 0, 0);
}
/// <summary> /// <summary>
/// Converts to <see cref="Vector2" /> /// Converts to <see cref="Vector2" />
/// </summary> /// </summary>

View file

@ -1,6 +1,8 @@
#region usings #region usings
using System;
using OpenTK; using OpenTK;
using SM.Base.Animation;
#endregion #endregion
@ -33,23 +35,26 @@ namespace SM.Base.Types
/// </summary> /// </summary>
public float Z { get; set; } public float Z { get; set; }
/// <inheritdoc /> /// <summary>
protected override float GetLengthProcess() /// Interpolates the motion to the target.
/// </summary>
/// <param name="duration">How long the interpolation should take.</param>
/// <param name="to">The value it should interpolate.</param>
/// <param name="interpolationCurve">The curve how he interpolates. Preset values can be found under <see cref="AnimationCurves"/>. Default: <see cref="AnimationCurves.Linear"/></param>
/// <returns>A handle to control the interpolation process.</returns>
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;
} }
/// <inheritdoc />
protected override void NormalizationProcess(float length)
{
base.NormalizationProcess(length);
Z *= length;
}
/// <inheritdoc /> /// <inheritdoc />
public override string ToString() public override string ToString()
{ {
return "{" + X + "; " + Y + "}"; return "{" + X + "; " + Y + "; "+Z+"}";
} }
/// <inheritdoc /> /// <inheritdoc />
@ -76,6 +81,13 @@ namespace SM.Base.Types
Set(vector.X, vector.Y, vector.Z, triggerChanged); Set(vector.X, vector.Y, vector.Z, triggerChanged);
} }
/// <inheritdoc />
public override void Set(params float[] parameters)
{
base.Set(parameters);
Z = parameters[2];
}
/// <inheritdoc /> /// <inheritdoc />
public override void Add(float uniform, bool triggerChanged = true) public override void Add(float uniform, bool triggerChanged = true)
{ {
@ -106,6 +118,24 @@ namespace SM.Base.Types
base.Add(x, y, triggerChanged); base.Add(x, y, triggerChanged);
} }
/// <inheritdoc />
protected override float GetLengthProcess()
{
return base.GetLengthProcess() + Z * Z;
}
/// <inheritdoc />
protected override void NormalizationProcess(float length)
{
base.NormalizationProcess(length);
Z *= length;
}
/// <inheritdoc />
protected override Vector4 ConvertToVector4()
{
return new Vector4(X, Y, Z, 0);
}
/// <summary> /// <summary>
/// Converts to <see cref="Vector3" /> /// Converts to <see cref="Vector3" />
/// </summary> /// </summary>

View file

@ -0,0 +1,139 @@
using System;
using System.Windows.Forms;
using OpenTK;
using SM.Base.Animation;
namespace SM.Base.Types
{
/// <inheritdoc />
public class CVector4 : CVector3
{
/// <summary>
/// The W-component.
/// </summary>
public float W { get; set; }
/// <inheritdoc />
public CVector4(float uniform) : base(uniform)
{
W = uniform;
}
/// <inheritdoc />
public CVector4(float x, float y, float z, float w) : base(x, y, z)
{
W = w;
}
/// <summary>
/// Interpolates the motion to the target.
/// </summary>
/// <param name="duration">How long the interpolation should take.</param>
/// <param name="to">The value it should interpolate.</param>
/// <param name="interpolationCurve">The curve how he interpolates. Preset values can be found under <see cref="AnimationCurves"/>. Default: <see cref="AnimationCurves.Linear"/></param>
/// <returns>A handle to control the interpolation process.</returns>
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;
}
/// <inheritdoc />
public override void Set(float uniform, bool triggerChanged = true)
{
W = uniform;
base.Set(uniform, triggerChanged);
}
/// <summary>
/// Sets the a own value to each component.
/// </summary>
public void Set(float x, float y, float z, float w, bool triggerChanged = true)
{
W = w;
base.Set(x, y, z, triggerChanged);
}
/// <summary>
/// Sets each component to the <see cref="Vector4" /> counter-part.
/// </summary>
public void Set(Vector4 vector, bool triggerChanged = true)
{
Set(vector.X, vector.Y, vector.Z, vector.W, triggerChanged);
}
/// <inheritdoc />
public override void Set(params float[] parameters)
{
base.Set(parameters);
W = parameters[3];
}
/// <inheritdoc />
public override void Add(float uniform, bool triggerChanged = true)
{
W += uniform;
base.Add(uniform, triggerChanged);
}
/// <summary>
/// Adds a <see cref="Vector4"/> to the CVector.
/// </summary>
/// <param name="vector"></param>
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
public void Add(Vector4 vector, bool triggerChanged = true)
{
Add(vector.X, vector.Y, vector.Z, vector.W, triggerChanged);
}
/// <summary>
/// Adds the values to the CVector.
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="z"></param>
/// <param name="w"></param>
/// <param name="triggerChanged">If false, the event Changed doesn't gets triggered </param>
public void Add(float x, float y, float z, float w, bool triggerChanged = true)
{
W = w;
base.Add(x, y, z, triggerChanged);
}
/// <inheritdoc />
public override string ToString()
{
return "{" + X + "; " + Y + "; " + Z + "; " + W + "}";
}
/// <inheritdoc />
protected override float GetLengthProcess()
{
return base.GetLengthProcess() + W * W;
}
/// <inheritdoc />
protected override void NormalizationProcess(float length)
{
base.NormalizationProcess(length);
W *= length;
}
/// <inheritdoc />
protected override Vector4 ConvertToVector4()
{
return new Vector4(X, Y, Z, W);
}
/// <summary>
/// Converts a <see cref="CVector4"/> into a <see cref="Vector4"/>.
/// </summary>
public static implicit operator Vector4(CVector4 vector) => new Vector4(vector.X, vector.Y, vector.Z, vector.W);
/// <summary>
/// Converts a <see cref="Vector4"/> into a <see cref="CVector4"/>.
/// </summary>
public static implicit operator CVector4(Vector4 vector) => new CVector4(vector.X, vector.Y, vector.Z, vector.W);
}
}

View file

@ -0,0 +1,83 @@
using System;
using OpenTK;
namespace SM.Base.Types
{
/// <summary>
/// Basis for the CVector classes
/// </summary>
public abstract class CVectorBase
{
/// <summary>
/// This event triggers when a component changed.
/// </summary>
public event Action Changed;
/// <summary>
/// The length/magnitute of the vector.
/// </summary>
public float Length => GetLength();
/// <summary>
/// Gets the square of the vector length (magnitude).
/// </summary>
/// <remarks>
/// This property avoids the costly square root operation required by the Length property. This makes it more suitable
/// for comparisons.
/// </remarks>
public float LengthSquared => GetLength(true);
/// <summary>
/// Get the length of the vector.
/// </summary>
/// <param name="squared">If true, it will return the squared product.</param>
/// <returns></returns>
public float GetLength(bool squared = false)
{
float length = GetLengthProcess();
if (squared) return length;
return (float)Math.Sqrt(length);
}
/// <summary>
/// Normalizes the vector.
/// </summary>
public void Normalize()
{
float length = GetLength();
NormalizationProcess(length);
}
/// <summary>
/// Sets the values of the vector, by providing the values over an array.
/// </summary>
/// <param name="parameters"></param>
public abstract void Set(params float[] parameters);
/// <summary>
/// This triggers the <see cref="Changed"/> event.
/// </summary>
protected void TriggerChanged()
{
Changed?.Invoke();
}
/// <summary>
/// Conversion from <see cref="float" /> to One-dimensional Vector.
/// </summary>
/// <returns></returns>
protected abstract float GetLengthProcess();
/// <summary>
/// Normalizes the vector.
/// </summary>
/// <param name="length"></param>
protected abstract void NormalizationProcess(float length);
/// <summary>
/// Converts the vector to a <see cref="Vector4"/>
/// </summary>
/// <returns></returns>
protected abstract Vector4 ConvertToVector4();
}
}

View file

@ -19,6 +19,7 @@ namespace SM2D.Scene
Transform.Size = new CVector2(1); Transform.Size = new CVector2(1);
} }
/// <inheritdoc />
public override void Draw(DrawContext context) public override void Draw(DrawContext context)
{ {
this.Sort(Comparitor); this.Sort(Comparitor);

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using OpenTK; using OpenTK;
using SM.Base.Animation;
using SM.Base.Controls; using SM.Base.Controls;
using SM.Base.Time; using SM.Base.Time;
using SM.Base.Window; using SM.Base.Window;
@ -17,6 +18,8 @@ namespace SM_TEST
private static GLWindow window; private static GLWindow window;
private static PolyLine line; private static PolyLine line;
private static DrawParticles particles; private static DrawParticles particles;
private static InterpolationProcess interpolation;
static void Main(string[] args) static void Main(string[] args)
{ {
window = new GLWindow(1280, 720, "0ms", WindowFlags.Window, VSyncMode.Off); window = new GLWindow(1280, 720, "0ms", WindowFlags.Window, VSyncMode.Off);
@ -25,12 +28,9 @@ namespace SM_TEST
window.SetScene(scene = new Scene()); window.SetScene(scene = new Scene());
particles = new DrawParticles(TimeSpan.FromSeconds(5)) 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));
MaxSpeed = 50, scene.Objects.Add(testObj);
};
particles.Transform.Size.Set(20);
scene.Objects.Add(particles);
window.UpdateFrame += WindowOnUpdateFrame; window.UpdateFrame += WindowOnUpdateFrame;
window.RenderFrame += Window_RenderFrame; window.RenderFrame += Window_RenderFrame;
@ -47,7 +47,9 @@ namespace SM_TEST
private static void WindowOnUpdateFrame(object sender, FrameEventArgs e) private static void WindowOnUpdateFrame(object sender, FrameEventArgs e)
{ {
if (Mouse.LeftClick) if (Mouse.LeftClick)
particles.Trigger(); interpolation.Stop();
if (Mouse.RightClick)
interpolation.Stop(false);
} }
} }
} }