@@ -701,27 +701,27 @@ void GetBinaryData(GltfShape shape, Gltf gltfFile, string gltfFileName)
701
701
702
702
var sampler = gltfAnimation . Samplers [ gltfChannel . Sampler ] ;
703
703
var inputAccessor = gltfFile . Accessors [ sampler . Input ] ;
704
- var readInput = GetNormalizedReader ( inputAccessor . ComponentType , shape . MsfsFlavoured ) ;
705
- var bri = new BinaryReader ( GetBufferView ( inputAccessor , out _ ) ) ;
706
704
var outputAccessor = gltfFile . Accessors [ sampler . Output ] ;
707
- var readOutput = GetNormalizedReader ( outputAccessor . ComponentType , shape . MsfsFlavoured ) ;
708
- var bro = new BinaryReader ( GetBufferView ( outputAccessor , out _ ) ) ;
705
+
706
+ var inputFloats = new Span < float > ( new float [ inputAccessor . Count * GetComponentNumber ( inputAccessor . Type ) ] ) ;
707
+ Denormalize ( inputAccessor , shape . MsfsFlavoured , GetBufferViewSpan ( inputAccessor ) , ref inputFloats ) ;
708
+ var outputFloats = new Span < float > ( new float [ outputAccessor . Count * GetComponentNumber ( outputAccessor . Type ) ] ) ;
709
+ Denormalize ( outputAccessor , shape . MsfsFlavoured , GetBufferViewSpan ( outputAccessor ) , ref outputFloats ) ;
709
710
710
711
GltfAnimationChannel channel ;
711
712
animation . Channels . Add ( channel = new GltfAnimationChannel
712
713
{
713
714
Interpolation = shape . MsfsFlavoured ? AnimationSampler . InterpolationEnum . LINEAR : sampler . Interpolation ,
714
715
Path = gltfChannel . Target . Path ,
715
716
TargetNode = gltfChannel . Target . Node ,
716
- TimeArray = new float [ inputAccessor . Count ] . Select ( _ => readInput ( bri ) ) . ToArray ( ) ,
717
+ TimeArray = inputFloats . ToArray ( ) ,
717
718
TimeMin = inputAccessor . Min [ 0 ] ,
718
719
TimeMax = inputAccessor . Max [ 0 ] ,
719
720
OutputQuaternion = gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . rotation ?
720
- new Quaternion [ outputAccessor . Count ] . Select ( _ => new Quaternion ( readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) ) ) . ToArray ( ) : null ,
721
+ MemoryMarshal . Cast < float , Quaternion > ( outputFloats ) . ToArray ( ) : null ,
721
722
OutputVector3 = gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . scale || gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . translation ?
722
- new Vector3 [ outputAccessor . Count ] . Select ( _ => new Vector3 ( readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) ) ) . ToArray ( ) : null ,
723
- OutputFloats = gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . weights ?
724
- new float [ outputAccessor . Count ] . Select ( _ => readOutput ( bro ) ) . ToArray ( ) : null ,
723
+ MemoryMarshal . Cast < float , Vector3 > ( outputFloats ) . ToArray ( ) : null ,
724
+ OutputFloats = gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . weights ? outputFloats . ToArray ( ) : null ,
725
725
Pointer = gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . pointer ? pointer : null ,
726
726
} ) ;
727
727
@@ -742,10 +742,10 @@ void GetBinaryData(GltfShape shape, Gltf gltfFile, string gltfFileName)
742
742
switch ( PointerTemplates [ template ] )
743
743
{
744
744
case PointerTypes . FloatVector :
745
- case PointerTypes . Float : channel . OutputFloats = new float [ outputAccessor . Count ] . Select ( _ => readOutput ( bro ) ) . ToArray ( ) ; break ;
746
- case PointerTypes . Quaternion : channel . OutputQuaternion = new Quaternion [ outputAccessor . Count ] . Select ( _ => new Quaternion ( readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) ) ) . ToArray ( ) ; break ;
747
- case PointerTypes . Vector3 : channel . OutputVector3 = new Vector3 [ outputAccessor . Count ] . Select ( _ => new Vector3 ( readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) ) ) . ToArray ( ) ; break ;
748
- case PointerTypes . Vector4 : channel . OutputVector4 = new Vector4 [ outputAccessor . Count ] . Select ( _ => new Vector4 ( readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) , readOutput ( bro ) ) ) . ToArray ( ) ; break ;
745
+ case PointerTypes . Float : channel . OutputFloats = outputFloats . ToArray ( ) ; break ;
746
+ case PointerTypes . Quaternion : channel . OutputQuaternion = MemoryMarshal . Cast < float , Quaternion > ( outputFloats ) . ToArray ( ) ; break ;
747
+ case PointerTypes . Vector3 : channel . OutputVector3 = MemoryMarshal . Cast < float , Vector3 > ( outputFloats ) . ToArray ( ) ; break ;
748
+ case PointerTypes . Vector4 : channel . OutputVector4 = MemoryMarshal . Cast < float , Vector4 > ( outputFloats ) . ToArray ( ) ; break ;
749
749
default : break ;
750
750
}
751
751
break ;
@@ -872,6 +872,23 @@ bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchPro
872
872
}
873
873
}
874
874
875
+ internal static void Denormalize ( Accessor accessor , bool msfsFlavoured , Span < byte > bytes , ref Span < float > floats )
876
+ {
877
+ switch ( accessor . ComponentType )
878
+ {
879
+ case Accessor . ComponentTypeEnum . BYTE : for ( var i = 0 ; i < accessor . Count ; i ++ ) floats [ i ] = Math . Max ( bytes [ i ] / 127f , - 1f ) ; break ;
880
+ case Accessor . ComponentTypeEnum . UNSIGNED_BYTE : for ( var i = 0 ; i < accessor . Count ; i ++ ) floats [ i ] = bytes [ i ] / 255f ; break ;
881
+ case Accessor . ComponentTypeEnum . UNSIGNED_SHORT : for ( var i = 0 ; i < accessor . Count ; i ++ ) floats [ i ] = MemoryMarshal . Read < ushort > ( bytes . Slice ( i * sizeof ( ushort ) ) ) / 65535f ; break ;
882
+ case Accessor . ComponentTypeEnum . SHORT :
883
+ // Component type 5122 "SHORT" is a 16 bit int by the glTF specification, but is used as a 16 bit float (half) by asobo-msfs:
884
+ for ( var i = 0 ; i < accessor . Count ; i ++ )
885
+ floats [ i ] = msfsFlavoured ? ( float ) MemoryMarshal . Read < SharpDX . Half > ( bytes . Slice ( i * sizeof ( short ) ) ) : Math . Max ( MemoryMarshal . Read < short > ( bytes . Slice ( i * sizeof ( short ) ) ) / 32767f , - 1f ) ;
886
+ break ;
887
+ case Accessor . ComponentTypeEnum . FLOAT :
888
+ default : floats = MemoryMarshal . Cast < byte , float > ( bytes . Slice ( 0 , floats . Length * sizeof ( float ) ) ) ; break ;
889
+ }
890
+ }
891
+
875
892
internal Span < byte > GetBufferViewSpan ( AccessorSparseIndices accessor ) => GetBufferViewSpan ( accessor ? . BufferView , accessor ? . ByteOffset ?? 0 ) ;
876
893
internal Span < byte > GetBufferViewSpan ( AccessorSparseValues accessor ) => GetBufferViewSpan ( accessor ? . BufferView , accessor ? . ByteOffset ?? 0 ) ;
877
894
internal Span < byte > GetBufferViewSpan ( Accessor accessor ) => GetBufferViewSpan ( accessor . BufferView , accessor . ByteOffset ) ;
@@ -885,21 +902,6 @@ internal Span<byte> GetBufferViewSpan(int? bufferViewNumber, int accessorByteOff
885
902
return bytes . AsSpan ( bufferView . ByteOffset + accessorByteOffset ) ;
886
903
}
887
904
888
- internal Stream GetBufferView ( Accessor accessor , out int ? byteStride ) => GetBufferView ( accessor . BufferView , accessor . ByteOffset , out byteStride ) ;
889
- internal Stream GetBufferView ( int ? bufferViewNumber , int accessorByteOffset , out int ? byteStride )
890
- {
891
- byteStride = null ;
892
- if ( bufferViewNumber == null )
893
- return Stream . Null ;
894
- var bufferView = GltfFile . BufferViews [ ( int ) bufferViewNumber ] ;
895
- byteStride = bufferView . ByteStride ;
896
- if ( ! BinaryBuffers . TryGetValue ( bufferView . Buffer , out var bytes ) )
897
- BinaryBuffers . Add ( bufferView . Buffer , bytes = glTFLoader . Interface . LoadBinaryBuffer ( GltfFile , bufferView . Buffer , GltfFileName ) ) ;
898
- var stream = new MemoryStream ( bytes ) ;
899
- stream . Seek ( bufferView . ByteOffset + accessorByteOffset , SeekOrigin . Begin ) ;
900
- return stream ;
901
- }
902
-
903
905
internal int GetSizeInBytes ( Accessor accessor )
904
906
{
905
907
var componentNumber = GetComponentNumber ( accessor . Type ) ;
@@ -908,7 +910,7 @@ internal int GetSizeInBytes(Accessor accessor)
908
910
return size + padding ;
909
911
}
910
912
911
- int GetComponentNumber ( Accessor . TypeEnum type )
913
+ internal int GetComponentNumber ( Accessor . TypeEnum type )
912
914
{
913
915
switch ( type )
914
916
{
@@ -980,59 +982,6 @@ VertexElementFormat GetVertexElementFormat(Accessor accessor, bool msfsFlavoured
980
982
}
981
983
}
982
984
983
- internal static Func < BinaryReader , float > GetNormalizedReader ( Accessor . ComponentTypeEnum componentType , bool msfsFlavoured )
984
- {
985
- switch ( componentType )
986
- {
987
- case Accessor . ComponentTypeEnum . UNSIGNED_BYTE : return ( br ) => br . ReadByte ( ) / 255.0f ;
988
- case Accessor . ComponentTypeEnum . UNSIGNED_SHORT : return ( br ) => br . ReadUInt16 ( ) / 65535.0f ;
989
- case Accessor . ComponentTypeEnum . BYTE : return ( br ) => Math . Max ( br . ReadSByte ( ) / 127.0f , - 1.0f ) ;
990
- // Component type 5122 "SHORT" is a 16 bit int by the glTF specification, but is used as a 16 bit float (half) by asobo-msfs:
991
- case Accessor . ComponentTypeEnum . SHORT : return ( br ) => msfsFlavoured ? ToTwoByteFloat ( br . ReadBytes ( 2 ) ) : Math . Max ( br . ReadInt16 ( ) / 32767.0f , - 1.0f ) ; // the prior is br.ReadHalf() in fact
992
- case Accessor . ComponentTypeEnum . FLOAT :
993
- default : return ( br ) => br . ReadSingle ( ) ;
994
- }
995
- }
996
-
997
- internal static Func < BinaryReader , ushort > GetIntegerReader ( AccessorSparseIndices . ComponentTypeEnum componentType ) => GetIntegerReader ( ( Accessor . ComponentTypeEnum ) componentType ) ;
998
- internal static Func < BinaryReader , ushort > GetIntegerReader ( Accessor . ComponentTypeEnum componentType )
999
- {
1000
- switch ( componentType )
1001
- {
1002
- case Accessor . ComponentTypeEnum . BYTE : return ( br ) => ( ushort ) br . ReadSByte ( ) ;
1003
- case Accessor . ComponentTypeEnum . UNSIGNED_INT : return ( br ) => ( ushort ) br . ReadUInt32 ( ) ;
1004
- case Accessor . ComponentTypeEnum . UNSIGNED_BYTE : return ( br ) => br . ReadByte ( ) ;
1005
- case Accessor . ComponentTypeEnum . UNSIGNED_SHORT :
1006
- default : return ( br ) => br . ReadUInt16 ( ) ;
1007
- }
1008
- }
1009
-
1010
- static float ToTwoByteFloat ( byte [ ] bytes ) // Hi, Lo
1011
- {
1012
- var intVal = BitConverter . ToInt32 ( new byte [ ] { bytes [ 0 ] , bytes [ 1 ] , 0 , 0 } , 0 ) ;
1013
-
1014
- int mant = intVal & 0x03ff ;
1015
- int exp = intVal & 0x7c00 ;
1016
- if ( exp == 0x7c00 ) exp = 0x3fc00 ;
1017
- else if ( exp != 0 )
1018
- {
1019
- exp += 0x1c000 ;
1020
- if ( mant == 0 && exp > 0x1c400 )
1021
- return BitConverter . ToSingle ( BitConverter . GetBytes ( ( intVal & 0x8000 ) << 16 | exp << 13 | 0x3ff ) , 0 ) ;
1022
- }
1023
- else if ( mant != 0 )
1024
- {
1025
- exp = 0x1c400 ;
1026
- do
1027
- {
1028
- mant <<= 1 ;
1029
- exp -= 0x400 ;
1030
- } while ( ( mant & 0x400 ) == 0 ) ;
1031
- mant &= 0x3ff ;
1032
- }
1033
- return BitConverter . ToSingle ( BitConverter . GetBytes ( ( intVal & 0x8000 ) << 16 | ( exp | mant ) << 13 ) , 0 ) ;
1034
- }
1035
-
1036
985
internal static VertexElementUsage GetVertexElementSemantic ( string semantic , out int index )
1037
986
{
1038
987
var split = semantic . Split ( '_' ) ;
@@ -1651,17 +1600,9 @@ public GltfPrimitive(Material material, List<VertexBufferBinding> vertexAttribut
1651
1600
else
1652
1601
{
1653
1602
var accessor = gltfFile . Accessors [ ( int ) skin . InverseBindMatrices ] ;
1654
- InverseBindMatrices = new Matrix [ accessor . Count ] ;
1655
- var read = GltfDistanceLevel . GetNormalizedReader ( accessor . ComponentType , distanceLevel . Shape . MsfsFlavoured ) ;
1656
- using ( var br = new BinaryReader ( distanceLevel . GetBufferView ( accessor , out _ ) ) )
1657
- {
1658
- for ( var i = 0 ; i < InverseBindMatrices . Length ; i ++ )
1659
- InverseBindMatrices [ i ] = new Matrix (
1660
- read ( br ) , read ( br ) , read ( br ) , read ( br ) ,
1661
- read ( br ) , read ( br ) , read ( br ) , read ( br ) ,
1662
- read ( br ) , read ( br ) , read ( br ) , read ( br ) ,
1663
- read ( br ) , read ( br ) , read ( br ) , read ( br ) ) ;
1664
- }
1603
+ Span < float > inputFloats = stackalloc float [ accessor . Count * distanceLevel . GetComponentNumber ( accessor . Type ) ] ;
1604
+ GltfDistanceLevel . Denormalize ( accessor , distanceLevel . Shape . MsfsFlavoured , distanceLevel . GetBufferViewSpan ( accessor ) , ref inputFloats ) ;
1605
+ InverseBindMatrices = MemoryMarshal . Cast < float , Matrix > ( inputFloats ) . ToArray ( ) ;
1665
1606
}
1666
1607
distanceLevel . InverseBindMatrices . Add ( ( int ) skin . InverseBindMatrices , InverseBindMatrices ) ;
1667
1608
}
0 commit comments