Не удается передать контейнер MDLMesh с 3D-моделью как SCNGeometry

Я создаю приложение AR (Xcode 10.1, Swift 4.2.1).

Я хотел бы загрузить USDZ 3D-объект в пустую сцену SceneKit, а затем обработать его как MDL сетка.

Вот мой код:

import ARKit
import SceneKit.ModelIO

let scene = SCNScene(named: "art.scnassets/emptyScene.scn")!

if let filePath = Bundle.main.path(forResource: "Helicopter", 
                                        ofType: "usdz", 
                                   inDirectory: "art.scnassets") {

    let refURL = URL(fileURLWithPath: filePath)
    let refNode = SCNReferenceNode(url: refURL)
    refNode?.load()
    scene.rootNode.addChildNode(refNode!)
}

let helicopterGeo = refNode!.geometry

let mdlMesh = MDLMesh(scnGeometry: helicopterGeo!)      // ERROR APPEARS HERE
try! mdlMesh.makeVerticesUniqueAndReturnError()
let flattenedGeometry = SCNGeometry(mdlMesh: mdlMesh)
let flattenedNode = SCNNode(geometry: flattenedGeometry)
scene.rootNode.addChildNode(flattenedNode)

Но компилятор выдает мне ошибку:

"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"

Вопрос в том, какой подход я должен использовать для "Helicopter.usdz" геометрия к helicopterGeo постоянная?

Помогите мне найти обходной путь, пожалуйста!

Вы можете скачать USDZ файл для тестирования ЗДЕСЬ.

3 ответа

Решение

Это должно работать:

var scene: SCNScene!
if let filePath = Bundle.main.path(forResource: "Helicopter", 
                                    ofType: "usdz", 
                               inDirectory: "art.scnassets") {

    let refURL = URL(fileURLWithPath: filePath)
    let mdlAsset = MDLAsset(url: refURL)
    scene = SCNScene(mdlAsset: mdlAsset)

}

SCNReferenceNode работает только для файлов.scn. Затем вы можете получить геометрию от дочернего узла rootNode из scene,

let helicopterNode = scene.rootNode.childNode(withName: "helicopter", recursively: true)
let geometry = helicopterNode.geometry!

редактировать

Используя один из файлов из галереи быстрого просмотра AR, мне удалось заставить этот код работать. Основная проблема, с которой я столкнулся, заключалась в названии конкретного дочернего узла, который назывался "RetroTV", но к нему не было привязано никакой геометрии, он был просто родительским для обоих "RetroTVBody" и "RetroTVScreen". Единственная проблема заключается в том, что он не загружает текстуры для геометрии.

var scene: SCNScene!
if let filePath = Bundle.main.path(forResource: "retrotv",
                                   ofType: "usdz",
                                   inDirectory: "art.scnassets") {

    let refURL = URL(fileURLWithPath: filePath)
    let mdlAsset = MDLAsset(url: refURL)
    scene = SCNScene(mdlAsset: mdlAsset)

    let tvNode = scene.rootNode.childNode(withName: "RetroTVBody", recursively: true)
    let geometry = tvNode!.geometry!

} else {

    print("invalid path!")

}

Приведенный выше код также работает с tvNode а также geometry декларации вне if let заявление.

У меня нет точного ответа, но в вашей ситуации я хотел бы изучить иерархию refNode,

Поместите точку останова после ее загрузки и используйте отладчик, чтобы увидеть, есть ли у него дочерние элементы. У этих детей есть геометрия? У них есть дети с геометрией?

При создании 3D-ресурсов иногда несколько разделов будут группироваться на родительском узле, а во многих случаях этот родительский узел пуст.

Была ли это ошибка в бинарном файле Maya или ошибка usdz преобразование - я не знаю точно. Xcode не видит правильное имя объекта в простейшей иерархии Scene graph: Вместо pHelicopter1 это только показало Helicopter, Мой 3D-объект был сделан из pCube1 используя полигональные Extrude инструмент.

Вот окончательный код, и он отлично работает:

import ARKit
import SceneKit.ModelIO

//..........................................................

var scene = SCNScene(named: "art.scnassets/EmptyScene.scn")!

if let filePath = Bundle.main.path(forResource: "Helicopter",
                                        ofType: "usdz",
                                   inDirectory: "art.scnassets") {

    let refURL = URL(fileURLWithPath: filePath)
    let mdlAsset = MDLAsset(url: refURL)
    scene = SCNScene(mdlAsset: mdlAsset)
    let helicopterNode = scene.rootNode.childNode(withName: "pHelicopter1", 
                                               recursively: true)

    let geometry = helicopterNode!.geometry!
    let mdlMesh = MDLMesh(scnGeometry: geometry)
    try! mdlMesh.makeVerticesUniqueAndReturnError()
    let flattenedGeometry = SCNGeometry(mdlMesh: mdlMesh)
    let flattenedNode = SCNNode(geometry: flattenedGeometry)
    scene.rootNode.addChildNode(flattenedNode)

} else {
    print("Invalid path!")
}

введите описание изображения здесь

Другие вопросы по тегам