Как загрузить файл .dae в SCNNode в iOS SceneKit?

У меня возникли проблемы с пониманием того, как геометрия из файлов .dae должна быть загружена в график сцены iOS SceneKit.

Я знаю, что вы можете загружать файлы .dae непосредственно в SCNScene:

// create a new scene
let scene = SCNScene("test.scnassets/test.dae")

Я также знаю, что вы можете создать пустой SCNScene и добавить в него встроенные 3D-объекты как дочерние узлы:

let scene = SCNScene()
var sphereNode = SCNNode()
sphereNode.geometry = SCNSphere(radius: 1.0)
scene.rootNode.addChildNode(sphereNode)

Во втором случае вы можете загрузить файл .dae в SCNNode вместо использования встроенных объектов? Или ожидается, что все файлы .dae необходимо сначала загрузить в SCNScene?

Если последнее верно, то как же вы поместите объекты SCNNode в нужное место в иерархии графа сцены под SCNScene? EDIT # 1:

Теперь это работает для меня, это модифицированная версия того, что предложил @FlippinFun.

let url = NSBundle.mainBundle().URLForResource("test.scnassets/test", withExtension: "dae")
let source = SCNSceneSource(URL: url, options: nil)
let block = source.entryWithIdentifier("ID10", withClass: SCNGeometry.self) as SCNGeometry
scene.rootNode.addChildNode(SCNNode(geometry: block))

Но может быть, есть лучший способ? Вышеупомянутое включает в себя ручную загрузку каждого идентификатора из дерева .dae. В моем файле есть node "SketchUp" с дочерними идентификаторами "ID2" и "ID10". Этот метод не позволит вам загрузить корневой "SketchUp". (Я получаю ошибку времени выполнения.)

Ответы

Ответ 1

Обычным шаблоном является загрузка вашей сцены и извлечение node, которое вас интересует, с его именем, используя

[scene.rootNode childNodeWithName:aName recursively:YES];

Затем вы можете отследить этот node к вашей основной сцене.

Ответ 2

У меня была аналогичная проблема, когда у меня был один файл .dae, и я хотел загрузить несколько узлов из этого файла в node. Это сработало для меня:

var node = SCNNode()
let scene = SCNScene(named: "helloScene.dae")
var nodeArray = scene.rootNode.childNodes

for childNode in nodeArray {
  node.addChildNode(childNode as SCNNode)
}

Сначала я установил node, который будет удерживать все вместе, чтобы он выглядел так, как в исходном файле. Затем мы импортируем файл .dae, который хотим, и скопируем все его узлы. Наконец, для каждого node в массиве я добавил его в node.

Ответ 3

Спасибо за вашу помощь!

Вот простой класс collada2Node.

//collada2SCNNode
class func collada2SCNNode(filepath:String) -> SCNNode {
    var node = SCNNode()
    let scene = SCNScene(named: filepath)
    var nodeArray = scene!.rootNode.childNodes

    for childNode in nodeArray {
        node.addChildNode(childNode as SCNNode)
    }
    return node
}

Ответ 4

func nodeWithFile(path: String) -> SCNNode {

    if let scene = SCNScene(named: path) {

        let node = scene.rootNode.childNodes[0] as SCNNode
        return node

    } else {
        println("Invalid path supplied")
        return SCNNode()
    }

}

Ответ 5

Следующие ответы не помогли мне.

Вот что сработало для меня в Xcode 7.0 beta 5, iOS 9.0 beta/Swift 2.0:

Тип 3D модели: Collada Название 3D модели: "model.dae"

  • Загрузите сцену:

    let lampScene = SCNScene(named: "art.scnassets/model.dae")

  • Доступ к дочернему SCNode, который находится в SCNScene:

    let lampRootNode = lampScene?.rootNode.childNodes[0]

  • Добавьте лампу node из загруженной сцены в текущую загруженную и просматриваемую сцену:

    self.scene.rootNode.addChildNode(lampRootNode!)

ПРИМЕЧАНИЕ. self.scene существует из-за:

private var scene:SCNScene!

До добавления объекта в сцену я сделал некоторую настройку сцены в соответствии с примером набора сцен. Если вам нужен код, укажите его в комментариях.

Надеюсь, что это поможет.