Не удается передать контейнер MDLMesh с 3D-моделью как 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)
Но компилятор выдает мне ошибку:
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value"
Вопрос в том, какой подход я должен использовать для "Helicopter.usdz"
геометрия к helicopterGeo
постоянная?
Помогите мне найти обходной путь, пожалуйста!
Вы можете скачать USDZ
файл для тестирования ЗДЕСЬ.
3 ответа
Это должно работать:
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, мне удалось заставить этот код работать. Основная проблема, с которой я столкнулся, заключалась в названии конкретного дочернего узла, который назывался "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
заявление.
У меня нет точного ответа, но в вашей ситуации я хотел бы изучить иерархию refNode
,
Поместите точку останова после ее загрузки и используйте отладчик, чтобы увидеть, есть ли у него дочерние элементы. У этих детей есть геометрия? У них есть дети с геометрией?
При создании 3D-ресурсов иногда несколько разделов будут группироваться на родительском узле, а во многих случаях этот родительский узел пуст.
Была ли это ошибка в бинарном файле 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!")
}