簡體   English   中英

如何從 a.usdz 創建 SCNNode?

[英]How to create a SCNNode from a .usdz?

我下載了Apple提供的.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

然后我將它添加到場景中,結果是這樣的:

在此處輸入圖像描述

為什么它沒有紋理?

我已將 downloaded.usdz 文件放入項目目錄中的一個文件夾中,如您所見:

在此處輸入圖像描述

添加 .USDZ 對象的正確方法實際上是使用文件的 URL 創建場景:

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

甚至通過參考節點創建:

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

可以將 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()

將其包裹在一個節點中。

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

您現在可以在 ARKit 中附加此節點。 您需要在現實世界中將對象縮放和定向到您想要的位置,但該代碼取決於您要執行的操作,因此我已將其排除在外。

訪問內部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
}

不顯示的進一步紋理是不同的問題,可以通過向環境添加閃電來解決。

字面上的答案是 OP 忘記加載紋理。

這很容易做到,

asset.loadTextures()

對於 2023 年。讓 your.usdz 成為一個節點非常容易。

理解的秘訣是 a.usdz 文件包含(理論上)一個或多個不同的項目或字符。

秘訣是獲取文件中的“第一個”(唯一)字符。

幾乎總是,一個 usdz 文件只有一個 object。所以你只需取“第一個”(幾乎總是只有)object。

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、手機、mac 等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM