Skip to content

Commit 2f75eb7

Browse files
committed
Some animation code cleanup
1 parent 975c9c5 commit 2f75eb7

File tree

1 file changed

+44
-57
lines changed

1 file changed

+44
-57
lines changed

Source/RunActivity/Viewer3D/GltfShape.cs

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -769,9 +769,6 @@ internal void ConnectPointers()
769769
{
770770
foreach (var channel in animation.Channels)
771771
{
772-
if (string.IsNullOrEmpty(channel?.Pointer))
773-
continue;
774-
775772
bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchProperty)
776773
{
777774
var pointer = channel.Pointer.AsSpan();
@@ -797,7 +794,6 @@ bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchPro
797794

798795
if (isMatch("/nodes/", out var index, out var property))
799796
{
800-
// Wire back to the original behavior
801797
channel.TargetNode = index;
802798
switch (property.ToString())
803799
{
@@ -810,14 +806,12 @@ bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchPro
810806
&& int.TryParse(property.Slice(i2).ToString(), out var index2))
811807
{
812808
channel.SetTargetFloat = (f) => Shape.Weights[(int)channel.TargetNode][index2] = f;
813-
channel.TargetNode = null;
814809
}
815810
break;
816811
}
817812
}
818813
else if (isMatch("/meshes/", out index, out property))
819814
{
820-
// Wire back to the original behavior
821815
channel.TargetNode = Shape.Meshes[index].HierarchyIndex;
822816
if (property.SequenceEqual("/weights".AsSpan()))
823817
{
@@ -827,7 +821,6 @@ bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchPro
827821
&& int.TryParse(property.Slice(i2).ToString(), out var index2))
828822
{
829823
channel.SetTargetFloat = (f) => Shape.Weights[(int)channel.TargetNode][index2] = f;
830-
channel.TargetNode = null;
831824
}
832825
}
833826
else if (isMatch("/materials/", out index, out property))
@@ -861,6 +854,20 @@ bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchPro
861854
default: channel.SetTargetFloat = null; channel.SetTargetVector3 = null; channel.SetTargetVector4 = null; break;
862855
}
863856
}
857+
if (channel.TargetNode != null)
858+
{
859+
switch (channel.Path)
860+
{
861+
case AnimationChannelTarget.PathEnum.rotation: channel.SetTargetQuaternion = (v) => Rotations[(int)channel.TargetNode] = v; break;
862+
case AnimationChannelTarget.PathEnum.translation: channel.SetTargetVector3 = (v) => Translations[(int)channel.TargetNode] = v; break;
863+
case AnimationChannelTarget.PathEnum.scale: channel.SetTargetVector3 = (v) => Scales[(int)channel.TargetNode] = v; break;
864+
case AnimationChannelTarget.PathEnum.weights:
865+
channel.SetTargetFloatVector = (i, f) => Weights[(int)channel.TargetNode][i] = f;
866+
channel.TargetFloatVectorLength = Weights[(int)channel.TargetNode].Length;
867+
break;
868+
}
869+
continue;
870+
}
864871
}
865872
}
866873
}
@@ -1882,57 +1889,34 @@ public void Animate(int animationNumber, float time, Matrix[] animatedMatrices)
18821889
var time1 = channel.TimeArray[frame1];
18831890
var time2 = channel.TimeArray[frame2];
18841891

1885-
float amount;
1886-
switch (channel.Interpolation)
1892+
float amount = 0;
1893+
if (channel.Interpolation != AnimationSampler.InterpolationEnum.STEP && time1 < time2)
1894+
amount = MathHelper.Clamp((time - time1) / (time2 - time1), 0, 1);
1895+
1896+
// See the formula for cubic the spline: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic
1897+
channel.SetTargetVector3?.Invoke(channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1898+
? Vector3.Hermite(channel.OutputVector3[Property(frame1)], channel.OutputVector3[OutTangent(frame2)], channel.OutputVector3[Property(frame2)], channel.OutputVector3[InTangent(frame2)], amount)
1899+
: Vector3.Lerp(channel.OutputVector3[frame1], channel.OutputVector3[frame2], amount));
1900+
channel.SetTargetVector4?.Invoke(channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1901+
? Vector4.Hermite(channel.OutputVector4[Property(frame1)], channel.OutputVector4[OutTangent(frame2)], channel.OutputVector4[Property(frame2)], channel.OutputVector4[InTangent(frame2)], amount)
1902+
: Vector4.Lerp(channel.OutputVector4[frame1], channel.OutputVector4[frame2], amount));
1903+
channel.SetTargetFloat?.Invoke(channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1904+
? MathHelper.Hermite(channel.OutputFloats[Property(frame1)], channel.OutputFloats[OutTangent(frame2)], channel.OutputFloats[Property(frame2)], channel.OutputFloats[InTangent(frame2)], amount)
1905+
: MathHelper.Lerp(channel.OutputFloats[frame1], channel.OutputFloats[frame2], amount));
1906+
channel.SetTargetQuaternion?.Invoke(((channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1907+
? CsInterp(channel.OutputQuaternion[Property(frame1)], channel.OutputQuaternion[OutTangent(frame2)], channel.OutputQuaternion[Property(frame2)], channel.OutputQuaternion[InTangent(frame2)], amount)
1908+
: Quaternion.Slerp(channel.OutputQuaternion[frame1], channel.OutputQuaternion[frame2], amount))
1909+
is var q && q != new Quaternion(0, 0, 0, 0)) ? Quaternion.Normalize(q) : Quaternion.Identity);
1910+
if (channel.SetTargetFloatVector != null && channel.TargetFloatVectorLength > 0)
18871911
{
1888-
// See the formula for cubic spline: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic
1889-
case AnimationSampler.InterpolationEnum.CUBICSPLINE:
1890-
case AnimationSampler.InterpolationEnum.LINEAR: amount = time1 < time2 ? MathHelper.Clamp((time - time1) / (time2 - time1), 0, 1) : 0; break;
1891-
case AnimationSampler.InterpolationEnum.STEP: amount = 0; break;
1892-
default: amount = 0; break;
1912+
var count = channel.TargetFloatVectorLength;
1913+
for (var i = 0; i < count; i++)
1914+
channel.SetTargetFloatVector(i, channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1915+
? MathHelper.Hermite(channel.OutputFloats[Property(frame1) * count + i], channel.OutputFloats[OutTangent(frame2) * count + i], channel.OutputFloats[Property(frame2) * count + i], channel.OutputFloats[InTangent(frame2) * count + i], amount)
1916+
: MathHelper.Lerp(channel.OutputFloats[frame1 * count + i], channel.OutputFloats[frame2 * count + i], amount));
18931917
}
1894-
if (channel.TargetNode != null)
1895-
{
1896-
switch (channel.Path)
1897-
{
1898-
case AnimationChannelTarget.PathEnum.translation:
1899-
Translations[(int)channel.TargetNode] = channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1900-
? Vector3.Hermite(channel.OutputVector3[Property(frame1)], channel.OutputVector3[OutTangent(frame2)], channel.OutputVector3[Property(frame2)], channel.OutputVector3[InTangent(frame2)], amount)
1901-
: Vector3.Lerp(channel.OutputVector3[frame1], channel.OutputVector3[frame2], amount);
1902-
break;
1903-
case AnimationChannelTarget.PathEnum.rotation:
1904-
Rotations[(int)channel.TargetNode] = channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1905-
? CsInterp(channel.OutputQuaternion[Property(frame1)], channel.OutputQuaternion[OutTangent(frame2)], channel.OutputQuaternion[Property(frame2)], channel.OutputQuaternion[InTangent(frame2)], amount)
1906-
: Quaternion.Slerp(channel.OutputQuaternion[frame1], channel.OutputQuaternion[frame2], amount);
1907-
break;
1908-
case AnimationChannelTarget.PathEnum.scale:
1909-
Scales[(int)channel.TargetNode] = channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1910-
? Vector3.Hermite(channel.OutputVector3[Property(frame1)], channel.OutputVector3[OutTangent(frame2)], channel.OutputVector3[Property(frame2)], channel.OutputVector3[InTangent(frame2)], amount)
1911-
: Vector3.Lerp(channel.OutputVector3[frame1], channel.OutputVector3[frame2], amount);
1912-
break;
1913-
case AnimationChannelTarget.PathEnum.weights:
1914-
var count = Weights[(int)channel.TargetNode].Length;
1915-
for (var i = 0; i < count; i++)
1916-
Weights[(int)channel.TargetNode][i] = channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1917-
? MathHelper.Hermite(channel.OutputFloats[Property(frame1) * count + i], channel.OutputFloats[OutTangent(frame2) * count + i], channel.OutputFloats[Property(frame2) * count + i], channel.OutputFloats[InTangent(frame2) * count + i], amount)
1918-
: MathHelper.Lerp(channel.OutputFloats[frame1 * count + i], channel.OutputFloats[frame2 * count + i], amount);
1919-
break;
1920-
default: break;
1921-
}
1918+
if (channel.Path == AnimationChannelTarget.PathEnum.rotation || channel.Path == AnimationChannelTarget.PathEnum.scale || channel.Path == AnimationChannelTarget.PathEnum.translation)
19221919
animatedMatrices[(int)channel.TargetNode] = Matrix.CreateScale(Scales[(int)channel.TargetNode]) * Matrix.CreateFromQuaternion(Rotations[(int)channel.TargetNode]) * Matrix.CreateTranslation(Translations[(int)channel.TargetNode]);
1923-
}
1924-
else if (channel.Path == AnimationChannelTarget.PathEnum.pointer && !string.IsNullOrEmpty(channel.Pointer))
1925-
{
1926-
channel.SetTargetFloat?.Invoke(channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1927-
? MathHelper.Hermite(channel.OutputFloats[Property(frame1)], channel.OutputFloats[OutTangent(frame2)], channel.OutputFloats[Property(frame2)], channel.OutputFloats[InTangent(frame2)], amount)
1928-
: MathHelper.Lerp(channel.OutputFloats[frame1], channel.OutputFloats[frame2], amount));
1929-
channel.SetTargetVector3?.Invoke(channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1930-
? Vector3.Hermite(channel.OutputVector3[Property(frame1)], channel.OutputVector3[OutTangent(frame2)], channel.OutputVector3[Property(frame2)], channel.OutputVector3[InTangent(frame2)], amount)
1931-
: Vector3.Lerp(channel.OutputVector3[frame1], channel.OutputVector3[frame2], amount));
1932-
channel.SetTargetVector4?.Invoke(channel.Interpolation == AnimationSampler.InterpolationEnum.CUBICSPLINE
1933-
? Vector4.Hermite(channel.OutputVector4[Property(frame1)], channel.OutputVector4[OutTangent(frame2)], channel.OutputVector4[Property(frame2)], channel.OutputVector4[InTangent(frame2)], amount)
1934-
: Vector4.Lerp(channel.OutputVector4[frame1], channel.OutputVector4[frame2], amount));
1935-
}
19361920
}
19371921
}
19381922

@@ -2126,8 +2110,8 @@ public GltfAnimation(string name)
21262110

21272111
class GltfAnimationChannel
21282112
{
2129-
public int? TargetNode; // ref to index in hierarchy, e.g. Matrices(index)
2130-
public AnimationChannelTarget.PathEnum Path; // e.g. rotation or tcb_rot, translation or linear_pos, scale, tcb_pos
2113+
public int? TargetNode;
2114+
public AnimationChannelTarget.PathEnum Path;
21312115
public AnimationSampler.InterpolationEnum Interpolation;
21322116
public float[] TimeArray;
21332117
public float TimeMin;
@@ -2141,5 +2125,8 @@ class GltfAnimationChannel
21412125
public Action<float> SetTargetFloat;
21422126
public Action<Vector3> SetTargetVector3;
21432127
public Action<Vector4> SetTargetVector4;
2128+
public Action<Quaternion> SetTargetQuaternion;
2129+
public Action<int, float> SetTargetFloatVector;
2130+
public int TargetFloatVectorLength;
21442131
}
21452132
}

0 commit comments

Comments
 (0)