@@ -450,6 +450,90 @@ private class GLTF: Decodable {
450450 }
451451 }
452452 }
453+
454+ func animationValues< T: BinaryFloatingPoint > ( forAccessor accessorIndex: Int ) async -> [ T ] ? {
455+ let accessor = accessors [ accessorIndex]
456+ let bufferView = bufferViews [ accessor. bufferView]
457+ let count = accessor. count * accessor. primitiveCount
458+
459+ return buffer ( at: bufferView. buffer) ? . withUnsafeBytes {
460+ switch accessor. componentType {
461+ case . uint8:
462+ typealias Scalar = UInt8
463+ let size = MemoryLayout< Scalar> . size
464+ var array : [ Scalar ] = [ ]
465+ array. reserveCapacity ( count)
466+ for index in 0 ..< count {
467+ let offset = ( index * size) + bufferView. byteOffset
468+ array. append (
469+ Scalar ( littleEndian: $0. load ( fromByteOffset: offset, as: Scalar . self) )
470+ )
471+ }
472+ return array. map ( { T ( $0) / 255.0 } )
473+ case . uint16:
474+ typealias Scalar = UInt16
475+ let size = MemoryLayout< Scalar> . size
476+ var array : [ Scalar ] = [ ]
477+ array. reserveCapacity ( count)
478+ for index in 0 ..< count {
479+ let offset = ( index * size) + bufferView. byteOffset
480+ array. append (
481+ Scalar ( littleEndian: $0. load ( fromByteOffset: offset, as: Scalar . self) )
482+ )
483+ }
484+ return array. map ( { T ( $0) / 65535.0 } )
485+ case . uint32:
486+ typealias Scalar = UInt32
487+ let size = MemoryLayout< Scalar> . size
488+ var array : [ Scalar ] = [ ]
489+ array. reserveCapacity ( count)
490+ for index in 0 ..< count {
491+ let offset = ( index * size) + bufferView. byteOffset
492+ array. append (
493+ Scalar ( littleEndian: $0. load ( fromByteOffset: offset, as: Scalar . self) )
494+ )
495+ }
496+ return array. map ( { T ( $0) } )
497+ case . int8:
498+ typealias Scalar = Int8
499+ let size = MemoryLayout< Scalar> . size
500+ var array : [ Scalar ] = [ ]
501+ array. reserveCapacity ( count)
502+ for index in 0 ..< count {
503+ let offset = ( index * size) + bufferView. byteOffset
504+ array. append (
505+ Scalar ( littleEndian: $0. load ( fromByteOffset: offset, as: Scalar . self) )
506+ )
507+ }
508+ return array. map ( { . maximum( T ( $0) / 127.0 , - 1.0 ) } )
509+ case . int16:
510+ typealias Scalar = Int16
511+ let size = MemoryLayout< Scalar> . size
512+ var array : [ Scalar ] = [ ]
513+ array. reserveCapacity ( count)
514+ for index in 0 ..< count {
515+ let offset = ( index * size) + bufferView. byteOffset
516+ array. append (
517+ Scalar ( littleEndian: $0. load ( fromByteOffset: offset, as: Scalar . self) )
518+ )
519+ }
520+ return array. map ( { . maximum( T ( $0) / 32767.0 , - 1.0 ) } )
521+ case . float32:
522+ typealias Scalar = Float
523+ let size = MemoryLayout< Scalar> . size
524+ var array : [ Scalar ] = [ ]
525+ array. reserveCapacity ( count)
526+ for index in 0 ..< count {
527+ let offset = ( index * size) + bufferView. byteOffset
528+ let pattern = UInt32 (
529+ littleEndian: $0. load ( fromByteOffset: offset, as: UInt32 . self)
530+ )
531+ array. append ( Scalar ( bitPattern: pattern) )
532+ }
533+ return array. map ( { T ( $0) } )
534+ }
535+ }
536+ }
453537}
454538
455539// Helpers for exploring the gltf document
@@ -961,10 +1045,10 @@ extension GLTransmissionFormat: SkeletalAnimationImporter {
9611045
9621046 let sampler = animation. samplers [ channel. sampler]
9631047
964- guard let times: [ Float ] = await gltf. values ( forAccessor: sampler. input) else {
1048+ guard let times: [ Float ] = await gltf. animationValues ( forAccessor: sampler. input) else {
9651049 continue
9661050 }
967- guard let values: [ Float ] = await gltf. values ( forAccessor: sampler. output) else {
1051+ guard let values: [ Float ] = await gltf. animationValues ( forAccessor: sampler. output) else {
9681052 continue
9691053 }
9701054
@@ -978,8 +1062,10 @@ extension GLTransmissionFormat: SkeletalAnimationImporter {
9781062 switch sampler. interpolation {
9791063 case . step:
9801064 jointAnimation. positionOutput. interpolation = . step
981- default :
1065+ case . linear :
9821066 jointAnimation. positionOutput. interpolation = . linear
1067+ default :
1068+ throw GateEngineError . failedToDecode ( " Unhandled animation interpolation: \( sampler. interpolation) " )
9831069 }
9841070 case . rotation:
9851071 jointAnimation. rotationOutput. times = times
@@ -995,8 +1081,11 @@ extension GLTransmissionFormat: SkeletalAnimationImporter {
9951081 switch sampler. interpolation {
9961082 case . step:
9971083 jointAnimation. rotationOutput. interpolation = . step
998- default :
1084+ case . linear :
9991085 jointAnimation. rotationOutput. interpolation = . linear
1086+ default :
1087+ throw GateEngineError . failedToDecode ( " Unhandled animation interpolation: \( sampler. interpolation) " )
1088+
10001089 }
10011090 case . scale:
10021091 jointAnimation. scaleOutput. times = times
@@ -1010,8 +1099,10 @@ extension GLTransmissionFormat: SkeletalAnimationImporter {
10101099 switch sampler. interpolation {
10111100 case . step:
10121101 jointAnimation. scaleOutput. interpolation = . step
1013- default :
1102+ case . linear :
10141103 jointAnimation. scaleOutput. interpolation = . linear
1104+ default :
1105+ throw GateEngineError . failedToDecode ( " Unhandled animation interpolation: \( sampler. interpolation) " )
10151106 }
10161107 case . weight:
10171108 break
@@ -1031,6 +1122,13 @@ extension GLTransmissionFormat: SkeletalAnimationImporter {
10311122 if duration. isFinite == false {
10321123 duration = 0
10331124 }
1125+
1126+ // Slide animations to start at time zero
1127+ for animationKey in animations. keys {
1128+ animations [ animationKey] !. positionOutput. times = animations [ animationKey] !. positionOutput. times. map ( { $0 - timeMin} )
1129+ animations [ animationKey] !. rotationOutput. times = animations [ animationKey] !. rotationOutput. times. map ( { $0 - timeMin} )
1130+ animations [ animationKey] !. scaleOutput. times = animations [ animationKey] !. scaleOutput. times. map ( { $0 - timeMin} )
1131+ }
10341132
10351133 return RawSkeletalAnimation ( name: animation. name, duration: duration, animations: animations)
10361134 }
@@ -1070,8 +1168,10 @@ extension GLTransmissionFormat: ObjectAnimation3DImporter {
10701168 switch sampler. interpolation {
10711169 case . step:
10721170 objectAnimation. positionOutput. interpolation = . step
1073- default :
1171+ case . linear :
10741172 objectAnimation. positionOutput. interpolation = . linear
1173+ default :
1174+ throw GateEngineError . failedToDecode ( " Unhandled animation interpolation: \( sampler. interpolation) " )
10751175 }
10761176 case . rotation:
10771177 objectAnimation. rotationOutput. times = times
@@ -1087,8 +1187,10 @@ extension GLTransmissionFormat: ObjectAnimation3DImporter {
10871187 switch sampler. interpolation {
10881188 case . step:
10891189 objectAnimation. rotationOutput. interpolation = . step
1090- default :
1190+ case . linear :
10911191 objectAnimation. rotationOutput. interpolation = . linear
1192+ default :
1193+ throw GateEngineError . failedToDecode ( " Unhandled animation interpolation: \( sampler. interpolation) " )
10921194 }
10931195 case . scale:
10941196 objectAnimation. scaleOutput. times = times
@@ -1102,8 +1204,10 @@ extension GLTransmissionFormat: ObjectAnimation3DImporter {
11021204 switch sampler. interpolation {
11031205 case . step:
11041206 objectAnimation. scaleOutput. interpolation = . step
1105- default :
1207+ case . linear :
11061208 objectAnimation. scaleOutput. interpolation = . linear
1209+ default :
1210+ throw GateEngineError . failedToDecode ( " Unhandled animation interpolation: \( sampler. interpolation) " )
11071211 }
11081212 case . weight:
11091213 break
0 commit comments