@@ -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