import Foundation import OrderedCollections /* extension ObjMaterial { func convert() -> Material { var m = Material() m.diffuse = self.diffuse.setAlpha(self.alpha) if ![ .colour, .lambert, .shadowOnly ].contains(self.model) { m.specular = self.specular m.specularExp = self.specularExp } return m } } */ public struct ObjLoader: LoaderProtocol { public typealias T = Mesh public init() {} public func load(url: URL) -> T? { try? Self.read(url: url) } private static func read(url: URL) throws -> Mesh { return try read(model: try ObjReader.read(url: url)) } public static func read(model: ObjModel) throws -> Mesh { var subMeshes: OrderedDictionary = .init() var vertices = [Mesh.Vertex]() var indices = [UInt16]() let readIndex = { (v: ObjModel.Index) -> UInt16 in let vertex = Mesh.Vertex( position: model.positions[v.p], normal: model.normals[v.n], texCoord: model.texCoords[v.t]) if let index = vertices.firstIndex(of: vertex) { indices.append(UInt16(index)) return UInt16(index) } else { let index = UInt16(vertices.count) indices.append(index) vertices.append(vertex) return index } } for mesh in model.objects { let start = indices.count for face: ObjModel.Face in mesh.value.faces { switch face { case .triangle(let v1, let v2, let v3): for v in [ v1, v2, v3 ] { _ = readIndex(v) } case .quad(let v1, let v2, let v3, let v4): let n1 = readIndex(v1) _ = readIndex(v2) indices.append(readIndex(v3)) _ = readIndex(v4) indices.append(n1) case .ngon(_): fallthrough default: break } } let length = indices.count - start if length > 0 { subMeshes[mesh.key] = .init(start: start, length: length) } } return Mesh(vertices: vertices, indices: indices, subMeshes: subMeshes) } }