Не удается передать контейнер MDLMesh с 3D-моделью как SCNGeometry - PullRequest
0 голосов
/ 15 октября 2018

Я создаю приложение 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)

enter image description here

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

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

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

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

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

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

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

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

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

0 голосов
/ 16 ноября 2018

Была ли это ошибка в двоичном файле 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!")
}

enter image description here

0 голосов
/ 15 ноября 2018

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

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 Quick Look Gallery Мне удалось заставить этот код работать.Основная проблема, с которой я столкнулся, заключалась в названии конкретного дочернего узла, который назывался «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.

...