swift 如何从.usdz创建SCNNode?

7xllpg7q  于 2023-01-12  发布在  Swift
关注(0)|答案(4)|浏览(172)

我已经下载了苹果提供的.usdz模型:https://developer.apple.com/arkit/gallery/
但是现在,我想使用这些模型之一创建一个SCNNode,所以我这样做是为了获得节点:

guard let urlPath = Bundle.main.url(forResource: "retrotv", withExtension: "usdz") else {
    return
}
let mdlAsset = MDLAsset(url: urlPath)
let modelRootNode = SCNScene(mdlAsset: mdlAsset).rootNode

然后将其添加到场景中,结果如下:

为什么它没有纹理?
我将下载的.usdz文件放到了项目目录的一个文件夹中,如您所见:

0ve6wy6x

0ve6wy6x1#

添加.USDZ对象的正确方法实际上是使用文件的URL创建场景:

let scene = try! SCNScene(url: usdzURL, options: [.checkConsistency: true])

或者甚至通过参考节点创建:

let referenceNode = SCNReferenceNode(url: usdzURL)
 referenceNode.load()
zc0qhyus

zc0qhyus2#

可以将usdz加载到ARKit场景中。
重要的是这些进口

import ARKit
import SceneKit
import SceneKit.ModelIO

通过URL加载usdz。

guard let urlPath = Bundle.main.url(forResource: "retrotv", withExtension: "usdz") else {
    return
}
let mdlAsset = MDLAsset(url: urlPath)
// you can load the textures on an MDAsset so it's not white
mdlAsset.loadTextures()

将其 Package 在节点中。

let asset = mdlAsset.object(at: 0) // extract first object
let assetNode = SCNNode(mdlObject: asset)

现在你可以在ARKit中附加这个节点了,你需要将对象缩放和定向到真实的世界中你想要的位置,但是这个代码取决于你要做什么,所以我省略了这个。

s5a0g9ez

s5a0g9ez3#

字面上的答案是OP忘记加载纹理。

这很容易做到

asset.loadTextures()

适用于2023年。将您的.usdz设为节点非常简单。

理解的秘密是.usdz文件包含(理论上)***一个或多个***不同的项或字符。

秘诀是获取文件中的“第一个”(唯一的)字符。

几乎总是,一个usdz文件只有一个对象,所以你只需要取“第一个”(几乎总是唯一的)对象。

var fireDragon: SCNNode!

func loadDragonModel() {
  let p = Bundle.main.url(forResource: "Amy1", withExtension: "usdz")!
  let ass = MDLAsset(url: p)
  ass.loadTextures()
  fireDragon = SCNNode(mdlObject: ass.object(at: 0))
}

就这样。然后,

// .. some node of yours .. .addChildNode(fireDragon)
  // for example
  castleWall.addChildNode(fireDragon)

这适用于SceneKit和ARKit。

所有这些都适用于SceneKit和ARKit,它在tvOS,iOS,pad,phone,mac等上都能完美运行。

iyzzxitl

iyzzxitl4#

访问内部USDZ节点的正确方法

func usdzNodeFrom(file: String, exten: String, internal_node: String) -> SCNNode? {
    let rootNode = SCNNode()
    let scale = 1

    guard let fileUrl = Bundle.main.url(forResource: file, withExtension: exten) else {
        fatalError()
    }
    
    let scene = try! SCNScene(url: fileUrl, options: [.checkConsistency: true])
    let node = scene.rootNode.childNode(withName: internal_node, recursively: true)!
    node.name = internal_node
    let height = node.boundingBox.max.y - node.boundingBox.min.y
    node.position = SCNVector3(0, 0, 0)
    tNode.scale = SCNVector3(scale, scale, scale)
    rootNode.addChildNode(tNode)
    return rootNode
}

进一步的纹理不显示是不同的问题,可以通过向环境中添加 lightning 来解决。

相关问题