Home > Back-end >  Animate rotation node in Scenekit using CAKeyframeAnimation
Animate rotation node in Scenekit using CAKeyframeAnimation

Time:11-18

in order to study ARKit and SceneKit I'm writing a simple app which should do 2 things:

  1. place an airplane in a 3d world

  2. animate this plane in order to make this plane fly in a circular way (I'll be happy if I can make fly this airplane in a square path).

Now, I'm stuck on the second point, animate the plane.

I tried different approaches but not successful.

First try: Animate using "sequanceAction", but as you can you can see from the following code the plane first move to X that rotate(Yaxes) and than move in Z (the animation is very ugly).

func animataAirplane(nodeToAnimate: SCNNode){
    let moveinx = SCNAction.move(to: SCNVector3(nodeToAnimate.position.x   1,nodeToAnimate.position.y,nodeToAnimate.position.z), duration: 2)
    let rotateRight = SCNAction.rotate(by: deg2rad(-90), around: SCNVector3(0, 1, 0), duration: 1)
    let moveinz = SCNAction.move(to: SCNVector3(nodeToAnimate.position.x   1,nodeToAnimate.position.y,nodeToAnimate.position.z   1), duration: 2)
    let sequanceAction = SCNAction.sequence([moveinx, rotateRight, moveinz])
    nodeToAnimate.runAction(sequenceAction)
}

what I want is overly the animations, almost at the end of the moveX action start the rotation action and moveinZ, in order to give the illusion of a real plane turn.

Is that possible? I'm looking for someone point me in the right direction what I should look .

My second approach was try "CAKeyframeAnimation":

But I can't find exactly how to combine this animation:

func animatePlaneKey(nodeToAnimate: SCNNode){
    let pos = nodeToAnimate.position
    let animation = CAKeyframeAnimation(keyPath: "position")
    let pos1 = SCNVector3(pos.x, pos.y, pos.z)
    let pos2 = SCNVector3(pos.x   1 , pos.y, pos.z)
    let pos3 = SCNVector3(pos.x   1 , pos.y, pos.z   1)

    animation.values = [pos1,pos2, pos3]
    animation.keyTimes = [0,0.5,1]
    animation.calculationMode = .linear
    animation.duration = 10
    animation.repeatCount = 1
    animation.isAdditive = true
            
    let animation2 = CAKeyframeAnimation(keyPath: "rotation")
    let pos1rot = SCNVector3(nodeToAnimate.eulerAngles.x, nodeToAnimate.eulerAngles.y, nodeToAnimate.eulerAngles.z)
    let pos2rot = SCNVector3(nodeToAnimate.eulerAngles.x   Float(deg2rad(90)), nodeToAnimate.eulerAngles.y   Float(deg2rad(90)), nodeToAnimate.eulerAngles.z   Float(deg2rad(90)))
    animation2.values = [pos1rot,pos2rot]
    animation2.keyTimes = [0,1]
    animation2.duration = 2
    animation2.repeatCount = 1
    animation2.isAdditive = true
            
    nodeToAnimate.addAnimation(animation, forKey: "position")
    nodeToAnimate.addAnimation(animation2, forKey: "rotation")
}

Will be happy if someone can point me in the right direction in order to simulate this fly animation.

Thanks a lot.

CodePudding user response:

Here's a working version of your code:

func animatePlaneKey(nodeToAnimate: SCNNode) {

    let pos = nodeToAnimate.position
    let animation = CAKeyframeAnimation(keyPath: "position")
    let pos1 = SCNVector3(pos.x, pos.y, pos.z)
    let pos2 = SCNVector3(pos.x   1 , pos.y, pos.z)
    let pos3 = SCNVector3(pos.x   1 , pos.y, pos.z   1)

    animation.values = [pos1,pos2, pos3]
    animation.keyTimes = [0,0.5,1]
    animation.calculationMode = .linear
    animation.duration = 10
    animation.repeatCount = 1
    animation.isAdditive = true
            
    let animation2 = CAKeyframeAnimation(keyPath: "rotation")
    let pos1rot = SCNVector4(0, 0, 0, 0)
    let pos2rot = SCNVector4(0, 1, 0, CGFloat(Float.pi/2))
    animation2.values = [pos1rot, pos2rot]
    animation2.keyTimes = [0, 1]
    animation2.duration = 20
    animation2.repeatCount = 1
    animation2.isAdditive = true
            
    nodeToAnimate.addAnimation(animation, forKey: "position")
    nodeToAnimate.addAnimation(animation2, forKey: "spin around")
}
  • Related