import Foundation import Maths struct VMeshLoader: LoaderProtocol { typealias T = Mesh func load(url: URL) -> T? { try? Self.read(url: url) } func load(url: URL, content: inout ContentManager) -> T? { load(url: url) } static func read(url: URL) throws -> T { let file = try FileHandle(forReadingFrom: url) // read header fields let header = VMeshHeader( magic: try file.read(upToCount: 4), version: try file.read(as: UInt8.self).littleEndian, idxSize: try file.read(as: UInt8.self).littleEndian, subMeshCount: try file.read(as: UInt16.self).littleEndian, vertexCount: try file.read(as: UInt32.self).littleEndian, indexCount: try file.read(as: UInt32.self).littleEndian) // header sanity checks guard header.magic == Data("VMSH".utf8) else { throw NSError() } guard header.version == 2 else { throw NSError() } // check index type let idxSize = switch header.idxSize { case 1, 2, 4: header.idxSize default: throw NSError() } // fail on empty data lengths guard header.vertexCount > 0, header.indexCount > 0 else { throw NSError() } // read submeshes var subMeshes = [VMeshSubMesh](repeating: .empty, count: Int(header.subMeshCount)) for i in 0.. let texCoord: Vec2f let normal: SIMD4 let tangent: SIMD4 } extension VMeshVertex { static let empty: Self = .init(position: .init(), texCoord: .init(), normal: .init(), tangent: .init()) } struct VMeshSubMesh { let name: String let offset: UInt32, count: UInt32 } extension VMeshSubMesh { static let empty: Self = .init(name: .init(), offset: .init(), count: .init()) }