Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
504f2a2a4This file is pinned to the selected release. Download the original to open it in your design tool.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
namespace SharpGLTF.Animations
{
readonly struct SingleValueSampler<T> : ICurveSampler<T>, IConvertibleCurve<T>
{
#region lifecycle
public static ICurveSampler<T> CreateForSingle(IEnumerable<(float Key, T Value)> sequence)
{
if (sequence.Skip(1).Any()) return null;
return new SingleValueSampler<T>(sequence.First().Value);
}
public static ICurveSampler<T> CreateForSingle(IEnumerable<(float Key, (T, T, T) Value)> sequence)
{
if (sequence.Skip(1).Any()) return null;
return new SingleValueSampler<T>(sequence.First().Value.Item2);
}
private SingleValueSampler(T value)
{
_Value = value;
}
#endregion
#region data
private readonly T _Value;
#endregion
#region API
public int MaxDegree => 0;
public T GetPoint(float offset) { return _Value; }
public IReadOnlyDictionary<float, T> ToStepCurve()
{
return new Dictionary<float, T> { [0] = _Value };
}
public IReadOnlyDictionary<float, T> ToLinearCurve()
{
return new Dictionary<float, T> { [0] = _Value };
}
public IReadOnlyDictionary<float, (T TangentIn, T Value, T TangentOut)> ToSplineCurve()
{
return new Dictionary<float, (T TangentIn, T Value, T TangentOut)> { [0] = (default, _Value, default) };
}
#endregion
}
/// <summary>
/// Defines a <see cref="Vector3"/> curve sampler that can be sampled with STEP or LINEAR interpolations.
/// </summary>
readonly struct Vector3LinearSampler : ICurveSampler<Vector3>, IConvertibleCurve<Vector3>
{
#region lifecycle
public Vector3LinearSampler(IEnumerable<(float Key, Vector3 Value)> sequence, bool isLinear)
{
_Sequence = sequence;
_Linear = isLinear;
}
#endregion
#region data
private readonly IEnumerable<(float Key, Vector3 Value)> _Sequence;
private readonly Boolean _Linear;
#endregion
#region API
public int MaxDegree => _Linear ? 1 : 0;
public Vector3 GetPoint(float offset)
{
var (valA, valB, amount) = CurveSampler.FindRangeContainingOffset(_Sequence, offset);
if (!_Linear) return valA;
return Vector3.Lerp(valA, valB, amount);
}
public IReadOnlyDictionary<float, Vector3> ToStepCurve()
{
Guard.IsFalse(_Linear, nameof(MaxDegree), CurveSampler.StepCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, Vector3> ToLinearCurve()
{
Guard.IsTrue(_Linear, nameof(MaxDegree), CurveSampler.LinearCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, (Vector3 TangentIn, Vector3 Value, Vector3 TangentOut)> ToSplineCurve()
{
throw new NotSupportedException(CurveSampler.CurveError(MaxDegree));
}
public ICurveSampler<Vector3> ToFastSampler()
{
var linear = _Linear;
return FastCurveSampler<Vector3>.CreateFrom(_Sequence, chunk => new Vector3LinearSampler(chunk, linear)) ?? this;
}
#endregion
}
/// <summary>
/// Defines a <see cref="Quaternion"/> curve sampler that can be sampled with STEP or LINEAR interpolations.
/// </summary>
readonly struct QuaternionLinearSampler : ICurveSampler<Quaternion>, IConvertibleCurve<Quaternion>
{
#region lifecycle
public QuaternionLinearSampler(IEnumerable<(float, Quaternion)> sequence, bool isLinear)
{
_Sequence = sequence;
_Linear = isLinear;
}
#endregion
#region data
private readonly IEnumerable<(float Key, Quaternion Value)> _Sequence;
private readonly Boolean _Linear;
#endregion
#region API
public int MaxDegree => _Linear ? 1 : 0;
public Quaternion GetPoint(float offset)
{
var (valA, valB, amount) = CurveSampler.FindRangeContainingOffset(_Sequence, offset);
if (!_Linear) return valA;
return Quaternion.Slerp(valA, valB, amount);
}
public IReadOnlyDictionary<float, Quaternion> ToStepCurve()
{
Guard.IsFalse(_Linear, nameof(MaxDegree), CurveSampler.StepCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, Quaternion> ToLinearCurve()
{
Guard.IsTrue(_Linear, nameof(MaxDegree), CurveSampler.LinearCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, (Quaternion TangentIn, Quaternion Value, Quaternion TangentOut)> ToSplineCurve()
{
throw new NotSupportedException(CurveSampler.CurveError(MaxDegree));
}
public ICurveSampler<Quaternion> ToFastSampler()
{
var linear = _Linear;
return FastCurveSampler<Quaternion>.CreateFrom(_Sequence, chunk => new QuaternionLinearSampler(chunk, linear)) ?? this;
}
#endregion
}
/// <summary>
/// Defines a <see cref="Transforms.SparseWeight8"/> curve sampler that can be sampled with STEP or LINEAR interpolation.
/// </summary>
readonly struct SparseLinearSampler : ICurveSampler<Transforms.SparseWeight8>, IConvertibleCurve<Transforms.SparseWeight8>
{
#region lifecycle
public SparseLinearSampler(IEnumerable<(float Key, Transforms.SparseWeight8 Value)> sequence, bool isLinear)
{
_Sequence = sequence;
_Linear = isLinear;
}
#endregion
#region data
private readonly IEnumerable<(float Key, Transforms.SparseWeight8 Value)> _Sequence;
private readonly Boolean _Linear;
#endregion
#region API
public int MaxDegree => _Linear ? 1 : 0;
public Transforms.SparseWeight8 GetPoint(float offset)
{
var (valA, valB, amount) = CurveSampler.FindRangeContainingOffset(_Sequence, offset);
if (!_Linear) return valA;
var weights = Transforms.SparseWeight8.InterpolateLinear(valA, valB, amount);
return weights;
}
public IReadOnlyDictionary<float, Transforms.SparseWeight8> ToStepCurve()
{
throw new NotSupportedException(CurveSampler.CurveError(MaxDegree));
}
public IReadOnlyDictionary<float, Transforms.SparseWeight8> ToLinearCurve()
{
Guard.IsTrue(_Linear, nameof(MaxDegree), CurveSampler.LinearCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, (Transforms.SparseWeight8 TangentIn, Transforms.SparseWeight8 Value, Transforms.SparseWeight8 TangentOut)> ToSplineCurve()
{
throw new NotSupportedException(CurveSampler.CurveError(MaxDegree));
}
public ICurveSampler<Transforms.SparseWeight8> ToFastSampler()
{
var linear = _Linear;
return FastCurveSampler<Transforms.SparseWeight8>.CreateFrom(_Sequence, chunk => new SparseLinearSampler(chunk, linear)) ?? this;
}
#endregion
}
/// <summary>
/// Defines a <see cref="float"/>[] curve sampler that can be sampled with STEP or LINEAR interpolations.
/// </summary>
readonly struct ArrayLinearSampler : ICurveSampler<float[]>, IConvertibleCurve<float[]>
{
#region lifecycle
public ArrayLinearSampler(IEnumerable<(float, float[])> sequence, bool isLinear)
{
_Sequence = sequence;
_Linear = isLinear;
}
#endregion
#region data
private readonly IEnumerable<(float Key, float[] Value)> _Sequence;
private readonly Boolean _Linear;
#endregion
#region API
public int MaxDegree => _Linear ? 1 : 0;
public float[] GetPoint(float offset)
{
var (valA, valB, amount) = CurveSampler.FindRangeContainingOffset(_Sequence, offset);
if (!_Linear) return valA;
return CurveSampler.InterpolateLinear(valA, valB, amount);
}
public IReadOnlyDictionary<float, float[]> ToStepCurve()
{
Guard.IsFalse(_Linear, nameof(MaxDegree), CurveSampler.StepCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, float[]> ToLinearCurve()
{
Guard.IsTrue(_Linear, nameof(MaxDegree), CurveSampler.LinearCurveError);
return _Sequence.ToDictionary(pair => pair.Key, pair => pair.Value);
}
public IReadOnlyDictionary<float, (float[] TangentIn, float[] Value, float[] TangentOut)> ToSplineCurve()
{
throw new NotSupportedException(CurveSampler.CurveError(MaxDegree));
}
public ICurveSampler<float[]> ToFastSampler()
{
var linear = _Linear;
return FastCurveSampler<float[]>.CreateFrom(_Sequence, chunk => new ArrayLinearSampler(chunk, linear)) ?? this;
}
#endregion
}
}