Загрузить.obj в.scn с несколькими подобъектами, текстурами, материалами в SceneKit & Model I/O?
В настоящее время я работаю с большими файлами.obj в Apple SceneKit/Model I/O, которые содержат несколько объектов внутри, каждый с отдельными текстурами и материалами. Это означает, что я не могу применить одну текстуру к файлу, как предлагают многие другие посты формы. Есть ли хороший способ импортировать в материалы и текстуры?
У меня есть мои obj mtl и jpg в одном каталоге, где я также размещаю сцену scn.
Код в настоящее время соответствует этой схеме, где я обращаюсь к нему из соответствующего местоположения, загружаю его в набор MDLAsset, а затем помещаю в SCNScene, где он сохраняется обратно в файл для последующей загрузки в коде.
//...
// Get the mesh from the obj object
let asset = MDLAsset(url:url)
//asset.loadTextures()
guard let object = asset.object(at: 0) as? MDLMesh else {
fatalError("Failed to get mesh from obj asset.")
}
// Wrap the ModelIO object in a SceneKit object
let scene = SCNScene()
let node = SCNNode(mdlObject: object)
scene.rootNode.addChildNode(node)
// Get the document directory name the write a url for the object replacing its extention with scn
let dirPaths = FileManager().urls(for: .documentDirectory, in: .userDomainMask)
let fileUrl = dirPaths[0].appendingPathComponent(url.lastPathComponent.replacingOccurrences(of: ".obj", with: ".scn"))
// Write the scene to the new url
if !scene.write(to: fileUrl, delegate: nil) {
print("Failed to write scn scene to file!")
return nil
}
// ...
Функция MDLAsset.loadTextures не имеет документации и вызывает только утечку памяти, поэтому на момент написания этой статьи это не вариант. Открытие модели вручную и запуск конвертации в SCNScene также не работают, так как я все еще теряю материалы. Кроме того, я хочу, чтобы это было автоматизировано в коде, чтобы можно было загружать и преобразовывать модели во время выполнения.
Кажется, что для этого нет встроенного способа, кроме как делать каждую текстуру и материал вручную в коде, что легко, когда это только одна законченная текстура, но эта модель может иметь 100 различных материалов. Похоже, что мне нужно разобрать obj/mtl вручную, а затем создать и назначить материалы вручную. Это кажется совершенно неразумным, и я полагаю, что должен быть лучший способ, о котором я не знаю.
1 ответ
Когда вы импортируете OBJ-файл через Model I/O в качестве MDLAsset, он поступит как коллекция из одного или нескольких MDLMeshes. С сетками будут связаны MDLMaterials, а у MDLMaterial будут атрибуты. Эти атрибуты будут числовыми, путями к файлам или изображениями. Вам нужно перебрать свойства и проверить, есть ли путь.
https://developer.apple.com/documentation/modelio/mdlmaterialproperty
Если это так, то, скорее всего, это будет fileURL с тем же содержимым, что и в соответствующем MTL-файле OBJ-файла.
Свойства, описанные в функции MDLScatteringFunction, соответствуют различным свойствам в типичном файле MTL.
https://developer.apple.com/documentation/modelio/mdlscatteringfunction
MDLAsset.loadTextures добавит значение MDLTextureSampler к свойству, если Model IO действительно сможет найти текстуру, на которую есть ссылка в файле MTL.