SceneKit -– How to get animations for a .dae model?

前端 未结 1 1125
隐瞒了意图╮
隐瞒了意图╮ 2021-02-03 13:46

Ok, I am working with ARKit and SceneKit here and I am having trouble looking at the other questions dealing with just SceneKit trying to have a model in .dae forma

1条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-02-03 14:21

    At first I should confirm that CoreAnimation framework and some of its methods like animation(forKey:) instance method are really deprecated in iOS and macOS. But some parts of CoreAnimation framework are now implemented into SceneKit and other modules. In iOS 11+ and macOS 10.13+ you can use SCNAnimation class:

    let animation = CAAnimation(scnAnimation: SCNAnimation())
    

    and here SCNAnimation class has three useful initializers:

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

    In addition I should add that you can use not only animations baked in .dae file format, but also in .abc, .scn and .usdz.

    Also, you can use SCNSceneSource class (iOS 8+ and macOS 10.8+) to examine the contents of a SCNScene file or to selectively extract certain elements of a scene without keeping the entire scene and all the assets it contains.

    Here's how a code with implemented SCNSceneSource might look like:

    @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)
    }
    

    0 讨论(0)
提交回复
热议问题