@@ -701,27 +701,27 @@ void GetBinaryData(GltfShape shape, Gltf gltfFile, string gltfFileName)
701701
702702 var sampler = gltfAnimation . Samplers [ gltfChannel . Sampler ] ;
703703 var inputAccessor = gltfFile . Accessors [ sampler . Input ] ;
704- var readInput = GetNormalizedReader ( inputAccessor . ComponentType , shape . MsfsFlavoured ) ;
705- var bri = new BinaryReader ( GetBufferView ( inputAccessor , out _ ) ) ;
706704 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 ) ;
709710
710711 GltfAnimationChannel channel ;
711712 animation . Channels . Add ( channel = new GltfAnimationChannel
712713 {
713714 Interpolation = shape . MsfsFlavoured ? AnimationSampler . InterpolationEnum . LINEAR : sampler . Interpolation ,
714715 Path = gltfChannel . Target . Path ,
715716 TargetNode = gltfChannel . Target . Node ,
716- TimeArray = new float [ inputAccessor . Count ] . Select ( _ => readInput ( bri ) ) . ToArray ( ) ,
717+ TimeArray = inputFloats . ToArray ( ) ,
717718 TimeMin = inputAccessor . Min [ 0 ] ,
718719 TimeMax = inputAccessor . Max [ 0 ] ,
719720 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 ,
721722 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 ,
725725 Pointer = gltfChannel . Target . Path == AnimationChannelTarget . PathEnum . pointer ? pointer : null ,
726726 } ) ;
727727
@@ -742,10 +742,10 @@ void GetBinaryData(GltfShape shape, Gltf gltfFile, string gltfFileName)
742742 switch ( PointerTemplates [ template ] )
743743 {
744744 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 ;
749749 default : break ;
750750 }
751751 break ;
@@ -872,6 +872,23 @@ bool isMatch(string element, out int matchIndex, out ReadOnlySpan<char> matchPro
872872 }
873873 }
874874
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+
875892 internal Span < byte > GetBufferViewSpan ( AccessorSparseIndices accessor ) => GetBufferViewSpan ( accessor ? . BufferView , accessor ? . ByteOffset ?? 0 ) ;
876893 internal Span < byte > GetBufferViewSpan ( AccessorSparseValues accessor ) => GetBufferViewSpan ( accessor ? . BufferView , accessor ? . ByteOffset ?? 0 ) ;
877894 internal Span < byte > GetBufferViewSpan ( Accessor accessor ) => GetBufferViewSpan ( accessor . BufferView , accessor . ByteOffset ) ;
@@ -885,21 +902,6 @@ internal Span<byte> GetBufferViewSpan(int? bufferViewNumber, int accessorByteOff
885902 return bytes . AsSpan ( bufferView . ByteOffset + accessorByteOffset ) ;
886903 }
887904
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-
903905 internal int GetSizeInBytes ( Accessor accessor )
904906 {
905907 var componentNumber = GetComponentNumber ( accessor . Type ) ;
@@ -908,7 +910,7 @@ internal int GetSizeInBytes(Accessor accessor)
908910 return size + padding ;
909911 }
910912
911- int GetComponentNumber ( Accessor . TypeEnum type )
913+ internal int GetComponentNumber ( Accessor . TypeEnum type )
912914 {
913915 switch ( type )
914916 {
@@ -980,59 +982,6 @@ VertexElementFormat GetVertexElementFormat(Accessor accessor, bool msfsFlavoured
980982 }
981983 }
982984
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-
1036985 internal static VertexElementUsage GetVertexElementSemantic ( string semantic , out int index )
1037986 {
1038987 var split = semantic . Split ( '_' ) ;
@@ -1651,17 +1600,9 @@ public GltfPrimitive(Material material, List<VertexBufferBinding> vertexAttribut
16511600 else
16521601 {
16531602 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 ( ) ;
16651606 }
16661607 distanceLevel . InverseBindMatrices . Add ( ( int ) skin . InverseBindMatrices , InverseBindMatrices ) ;
16671608 }
0 commit comments