@@ -33,7 +33,7 @@ private class GLTF: Decodable {
3333 let scenes : [ Scene ]
3434 struct Scene : Decodable {
3535 let name : String
36- let nodes : [ Int ]
36+ let nodes : [ Int ] ?
3737 }
3838
3939 let nodes : [ Node ]
@@ -80,6 +80,14 @@ private class GLTF: Decodable {
8080 return transform
8181 }
8282 }
83+
84+ let images : [ Image ] ?
85+ struct Image : Decodable {
86+ let name : String
87+ let mimeType : String
88+ let uri : String ?
89+ let bufferView : Int ?
90+ }
8391
8492 let meshes : [ Mesh ] ?
8593 struct Mesh : Decodable {
@@ -216,7 +224,9 @@ private class GLTF: Decodable {
216224 }
217225
218226 lazy var cachedBuffers : [ Data ? ] = Array ( repeating: nil , count: buffers. count)
219- func buffer( at index: Int ) async -> Data ? {
227+ func buffer( at index: Int ) -> Data ? {
228+ // Buffer 0 is pre-cached for glb files
229+ // So `existing` will always be present for index 0 of a glb file
220230 if let existing = cachedBuffers [ index] {
221231 return existing
222232 }
@@ -227,7 +237,7 @@ private class GLTF: Decodable {
227237 let base64String = uri [ uri. index ( after: index) ... ]
228238 buffer = Data ( base64Encoded: String ( base64String) )
229239 } else {
230- buffer = try ? await Platform . current. loadResource (
240+ buffer = try ? Platform . current. synchronousLoadResource (
231241 from: self . baseURL!. appendingPathComponent ( uri) . path
232242 )
233243 }
@@ -242,7 +252,7 @@ private class GLTF: Decodable {
242252 let bufferView = bufferViews [ accessor. bufferView]
243253 let count = accessor. count * accessor. primitiveCount
244254
245- return await buffer ( at: bufferView. buffer) ? . withUnsafeBytes {
255+ return buffer ( at: bufferView. buffer) ? . withUnsafeBytes {
246256 switch accessor. componentType {
247257 case . uint8:
248258 typealias Scalar = UInt8
@@ -326,7 +336,7 @@ private class GLTF: Decodable {
326336 let bufferView = bufferViews [ accessor. bufferView]
327337 let count = accessor. count * accessor. primitiveCount
328338
329- return await buffer ( at: bufferView. buffer) ? . withUnsafeBytes {
339+ return buffer ( at: bufferView. buffer) ? . withUnsafeBytes {
330340 switch accessor. componentType {
331341 case . uint8:
332342 typealias Scalar = UInt8
@@ -561,16 +571,16 @@ extension GLTransmissionFormat: GeometryImporter {
561571 }
562572
563573 if geometries. count == 1 {
564- if options. applyRootTransform {
565- let transform = gltf. nodes [ gltf . scenes [ gltf . scene ] . nodes [ 0 ] ] . transform. createMatrix ( )
574+ if options. applyRootTransform, let nodeIndex = gltf . scenes [ gltf . scene ] . nodes ? [ 0 ] {
575+ let transform = gltf. nodes [ nodeIndex ] . transform. createMatrix ( )
566576 return geometries [ 0 ] * transform
567577 } else {
568578 return geometries [ 0 ]
569579 }
570580 } else {
571581 var geometry = RawGeometry ( geometries: geometries)
572- if options. applyRootTransform {
573- let transform = gltf. nodes [ gltf . scenes [ gltf . scene ] . nodes [ 0 ] ] . transform. createMatrix ( )
582+ if options. applyRootTransform, let nodeIndex = gltf . scenes [ gltf . scene ] . nodes ? [ 0 ] {
583+ let transform = gltf. nodes [ nodeIndex ] . transform. createMatrix ( )
574584 geometry = geometry * transform
575585 }
576586 return geometry
@@ -595,9 +605,11 @@ extension GLTransmissionFormat: SkinImporter {
595605 }
596606 return nil
597607 }
598- for index in gltf. scenes [ gltf. scene] . nodes {
599- if let value = findIn ( index) {
600- return value
608+ if let sceneNodes = gltf. scenes [ gltf. scene] . nodes {
609+ for index in sceneNodes {
610+ if let value = findIn ( index) {
611+ return value
612+ }
601613 }
602614 }
603615 return nil
@@ -608,7 +620,7 @@ extension GLTransmissionFormat: SkinImporter {
608620 in gltf: GLTF
609621 ) async -> [ Matrix4x4 ] ? {
610622 guard
611- let buffer = await gltf. buffer ( at: bufferView. buffer) ? . advanced (
623+ let buffer = gltf. buffer ( at: bufferView. buffer) ? . advanced (
612624 by: bufferView. byteOffset
613625 )
614626 else { return nil }
@@ -708,12 +720,14 @@ extension GLTransmissionFormat: SkeletonImporter {
708720 }
709721 return nil
710722 }
711- for index in gltf. scenes [ gltf. scene] . nodes {
712- if let value = findIn ( index) {
713- return value
723+ if let sceneNodes = gltf. scenes [ gltf. scene] . nodes {
724+ for index in sceneNodes {
725+ if let value = findIn ( index) {
726+ return value
727+ }
714728 }
715729 }
716- return gltf. scenes [ gltf. scene] . nodes. first
730+ return gltf. scenes [ gltf. scene] . nodes? . first
717731 }
718732
719733 public func process( data: Data , baseURL: URL , options: SkeletonImporterOptions ) async throws -> Skeleton . Joint {
@@ -881,7 +895,7 @@ extension GLTransmissionFormat: ObjectAnimation3DImporter {
881895
882896 var objectAnimation = ObjectAnimation3D . Animation ( )
883897
884- var timeMax : Float = - 1_000_000_000
898+ var timeMax : Float = . nan
885899
886900 for channel in animation. channels {
887901 let sampler = animation. samplers [ channel. sampler]
@@ -948,3 +962,43 @@ extension GLTransmissionFormat: ObjectAnimation3DImporter {
948962 return ObjectAnimation3DBackend ( name: animation. name, duration: timeMax, animation: objectAnimation)
949963 }
950964}
965+
966+ extension GLTransmissionFormat : TextureImporter {
967+ // TODO: Supports only PNG. Add other formats (JPEG, WebP, ...)
968+ public func loadTexture( options: TextureImporterOptions ) throws ( GateEngineError) -> ( data: Data , size: GameMath . Size2 ) {
969+ let imageData : Data
970+ func loadImageData( image: GLTF . Image ) throws ( GateEngineError) -> Data {
971+ if let uri = image. uri {
972+ return try Platform . current. synchronousLoadResource (
973+ from: self . gltf. baseURL!. appendingPathComponent ( uri) . path
974+ )
975+ } else if let bufferIndex = image. bufferView {
976+ let view = self . gltf. bufferViews [ bufferIndex]
977+
978+ if let buffer = self . gltf. buffer ( at: view. buffer) {
979+ return Data ( buffer [ view. byteOffset..< view. byteOffset+ view. byteLength] )
980+ } else {
981+ throw . failedToDecode( " The file does not contain a buffer with index: \( view. buffer) " )
982+ }
983+ } else {
984+ throw . failedToDecode( " The gltf file is using an unsupported feature or may be corrupt. " )
985+ }
986+ }
987+ if let name = options. subobjectName {
988+ if let image = self . gltf. images? . first ( where: { $0. name. caseInsensitiveCompare ( name) == . orderedSame} ) {
989+ imageData = try loadImageData ( image: image)
990+ } else {
991+ throw . failedToLoad( " No subobject found with name: \( name) " )
992+ }
993+ } else {
994+ if let image = self . gltf. images? . first {
995+ imageData = try loadImageData ( image: image)
996+ } else {
997+ throw . failedToLoad( " No images found in file. " )
998+ }
999+ }
1000+
1001+ let image = try PNGDecoder ( ) . decode ( imageData)
1002+ return ( image. data, Size2 ( Float ( image. width) , Float ( image. height) ) )
1003+ }
1004+ }
0 commit comments