SceneKit - 如何获取.dae模型的动画?

时间:2017-09-14 02:28:17

标签: swift animation scenekit maya arkit

好的,我正在使用ARKit和场景工具包,我正在查看其他问题,只处理场景工具包试图获得.dae格式的模型并加载各种动画以获得该模型运行 - 现在我们在iOS11中似乎有些解决方案不起作用。

以下是我如何获取模型 - 来自未应用动画的基础.dae场景。我用Maya导入这些 -

var modelScene = SCNScene(named: "art.scnassets/ryderFinal3.dae")!

if let d = modelScene.rootNode.childNodes.first {
    theDude.node = d
    theDude.setupNode()
}

然后在Dude班:

func setupNode() {
    node.scale = SCNVector3(x: modifier, y: modifier, z: modifier)
    center(node: node)
}

轴的缩放和居中需要,因为我的模型不在原点。那很有效。然后现在使用一个名为“Idle.dae”的不同场景,我尝试加载动画以便以后在模型上运行:

func animationFromSceneNamed(path: String) -> CAAnimation? {
    let scene  = SCNScene(named: path)
    var animation:CAAnimation?
    scene?.rootNode.enumerateChildNodes({ child, stop in
        if let animKey = child.animationKeys.first {
            animation = child.animation(forKey: animKey)
            stop.pointee = true
        }
    })
    return animation
}

我打算为我导入Xcode的所有动画场景执行此操作并将所有动画存储在

var animations = [CAAnimation]()

第一个Xcode说animation(forKey:已被弃用,这似乎不起作用(据我所知),将我的模型去中心和缩小到它的大小。它搞砸了它的位置,因为我希望让模型在动画中移动,例如,会使我游戏中的实例化模型捕捉到相同的位置。

和其他尝试导致崩溃。我对场景工具包非常陌生,并试图抓住如何正确设置我在场景中任何地方实例化的.dae模型的动画 -

  1. 在iOS11中如何加载一组动画以应用于他们的SCNNode?

  2. 你如何制作这样的动画是在模型上运行的模型是什么(不是将它攫取到其他位置)?

1 个答案:

答案 0 :(得分:0)

首先,我应该确认CoreAnimation框架及其某些方法(例如animation(forKey:)实例方法)在iOS和macOS中已被弃用。但是CoreAnimation框架的某些部分现在已实现到SceneKit和其他模块中。在iOS 11+和macOS 10.13+中,您可以使用SCNAnimation类:

let animation = CAAnimation(scnAnimation: SCNAnimation())

这里的SCNAnimation类具有三个有用的初始化程序:

SCNAnimation(caAnimation: CAAnimation())
SCNAnimation(contentsOf: URL())
SCNAnimation(named: String())

此外,我还要补充一点,您不仅可以使用以.dae文件格式烘焙的动画,还可以使用.abc.scn.usdz的动画。

此外,您可以使用SCNSceneSource类(iOS 8+和macOS 10.8+)检查SCNScene文件的内容或有选择地提取场景的某些元素而不保留整个场景及其包含的所有资产

以下是实现了SCNSceneSource的代码的样子:

@IBOutlet var sceneView: ARSCNView!
var animations = [String: CAAnimation]()
var idle: Bool = true

override func viewDidLoad() {
    super.viewDidLoad()
    sceneView.delegate = self

    let scene = SCNScene()
    sceneView.scene = scene
    
    loadMultipleAnimations()
}

func loadMultipleAnimations() {

    let idleScene = SCNScene(named: "art.scnassets/model.dae")!
    
    let node = SCNNode()
    
    for child in idleScene.rootNode.childNodes {
        node.addChildNode(child)
    }       
    node.position = SCNVector3(0, 0, -5)
    node.scale = SCNVector3(0.45, 0.45, 0.45)
    
    sceneView.scene.rootNode.addChildNode(node)
    
    loadAnimation(withKey: "walking", 
                sceneName: "art.scnassets/walk_straight", 
      animationIdentifier: "walk_version02")
}

...

func loadAnimation(withKey: String, sceneName: String, animationIdentifier: String) {

    let sceneURL = Bundle.main.url(forResource: sceneName, withExtension: "dae")
    let sceneSource = SCNSceneSource(url: sceneURL!, options: nil)

    if let animationObj = sceneSource?.entryWithIdentifier(animationIdentifier, 
                                                 withClass: CAAnimation.self) {
        animationObj.repeatCount = 1
        animationObj.fadeInDuration = CGFloat(1)
        animationObj.fadeOutDuration = CGFloat(0.5)

        animations[withKey] = animationObj
    }
}

...

func playAnimation(key: String) {

    sceneView.scene.rootNode.addAnimation(animations[key]!, forKey: key)
}