Загрузить .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, а затем вручную создал и назначил материалы. Это кажется совершенно неразумным, и я полагаю, что должен быть способ получше, о котором я не знаю.


person David Giangrave    schedule 24.05.2018    source источник


Ответы (1)


Когда вы импортируете файл OBJ через ввод-вывод модели как MDLAsset, он будет доставлен как набор из одного или нескольких MDLMeshes. С сетками будут связаны MDLMaterials, а у MDLMaterial будут атрибуты. Эти атрибуты будут числовыми, путями к файлам или изображениями. Вам нужно перебрать свойства и проверить, есть ли путь.

https://developer.apple.com/documentation/modelio/mdlmaterialproperty

Если есть, скорее всего, это будет URL-адрес файла с тем же содержимым, что и в связанном с ним MTL-файле OBJ-файла.

Свойства, описанные в функции MDLScatteringFunction, соответствуют различным свойствам типичного файла MTL.

https://developer.apple.com/documentation/modelio/mdlscatteringfunction

MDLAsset.loadTextures добавит значение MDLTextureSampler к свойству, если IO модели действительно может найти текстуру, указанную в файле MTL.

person Nick Porcino    schedule 10.09.2018
comment
Не совсем связаны, но как должны быть организованы файлы obj, mtl и текстуры? Мне никогда не удавалось заставить MDLAsset найти файл mtl или автоматически загрузить текстуры - person blueether; 01.11.2020