无法将具有3D模型的MDLMesh容器作为SCNGeometry提供

问题描述 投票:3回答:3

我正在创建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文件来测试HERE

swift scenekit augmented-reality arkit ios12
3个回答
1
投票

这应该工作:

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

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

Edit

使用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语句之外的geometryif let声明。


1
投票

我没有确切的答案,但我会在你的情况下做的是检查refNode的层次结构。

加载后放置断点并使用调试器查看它是否有任何子节点。那些孩子有几何形状吗?他们有几何形象的孩子吗?

创建3D资源时,有时会在父节点上对多个部分进行分组,并且在许多情况下父节点为空。


0
投票

是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

© www.soinside.com 2019 - 2024. All rights reserved.