无法将 3D 模型作为 SCNGeometry 提供给 MDLMesh 容器

Can't feed a MDLMesh container with 3D model as 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)


But compiler gives me an error:

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

问题是:我应该使用什么方法来分配"Helicopter.usdz" 几何到 helicopterGeo 常量?

请帮我找到解决方法!

您可以下载 USDZ 文件进行测试 HERE

这应该有效:

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 文件。然后,您可以从 scenerootNode 的子节点获取几何图形。

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!")

}

以上代码也适用于 if let 语句之外的 tvNodegeometry 声明。

我没有确切的答案,但在你的情况下我会做的是检查 refNode.

的层次结构

加载后打个断点,用调试器看看有没有children。那些 children 有什么几何形状吗?他们有children几何学吗?

创建3D资产时,有时多个部分会被分组到一个parent节点上,而在很多情况下parent节点是空的。

是 Maya 二进制文件中的错误,还是 usdz 转换的错误 – 我不清楚。 Xcode 没有在 Scene graph 的最简单层次结构中看到对象的正确名称:它只显示 Helicopter 而不是 pHelicopter1。我的 3D 对象是使用多边形 Extrude 工具从 pCube1 制作的。

这是最终代码,它运行良好:

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!")
}