简体   繁体   中英

Successive Morphing Animation in SceneKit

I struggle animating through different Morph-Targets in SceneKit. I have an array of morph-targets I want to iterate through an show them with an animation between each of them.

So from one geometry to the other, this is easy. In the SCNMorpher Class Reference there is an example to do this for one Morph-Geometry (morpher.weights[0]):

let animation = CABasicAnimation(keyPath: "morpher.weights[0]")
animation.fromValue = 0.0;
animation.toValue = 1.0;
animation.autoreverses = true;
animation.repeatCount = Float.infinity;
animation.duration = 5;

What I want to do is, to animate the morphs successive. I tried to setup several animations, for each target. But after completing the first animation, the weight of the first target is set to 0 again.

override func viewDidLoad() {
    super.viewDidLoad()

    // create a new scene
    let scene = SCNScene()

    let vbasic_geom: [Vertex] = [
        [ [0, 0, 0],      [+1.0, +0.0, +0.0] ],
        [ [0, 2, 0],      [+1.0, +0.0, +0.0] ],
        [ [2, 2, 0],      [+1.0, +0.0, +0.0] ]
    ]

    let vmorph1: [Vertex] = [
        [ [0, 0, 0],      [+1.0, +0.0, +0.0] ],
        [ [0, 4, 0],      [+1.0, +0.0, +0.0] ],
        [ [2, 2, 0],      [+1.0, +0.0, +0.0] ]
    ]

    let vmorph2: [Vertex] = [
        [ [0, 0, 0],      [+1.0, +0.0, +0.0] ],
        [ [0, 2, 0],      [+1.0, +0.0, +0.0] ],
        [ [4, 2, 0],      [+1.0, +0.0, +0.0] ]
    ]


    let basic_geom = gen_geometry(vbasic_geom)

    let morph1 = gen_geometry(vmorph1)

    let morph2 = gen_geometry(vmorph2)


    let morpher = SCNMorpher()
    morpher.targets = [morph1, morph2]

    let object = SCNNode(geometry: basic_geom)
    object.morpher = morpher

    //needed for model-layer refresh; implicit animation
    morpher.setWeight(1.0, forTargetAtIndex: 0)
    morpher.setWeight(1.0, forTargetAtIndex: 1)

    //set up animations
    let animation = CABasicAnimation(keyPath: "morpher.weights[0]")
    animation.fromValue = 0.0
    animation.toValue = 1.0
    animation.duration = 5
    animation.beginTime = 0.0
    animation.removedOnCompletion = false

    let animation2 = CABasicAnimation(keyPath: "morpher.weights[1]")
    animation2.fromValue = 0.0;
    animation2.toValue = 1.0
    animation2.duration = 5
    animation2.beginTime = 5.0
    animation.removedOnCompletion = false

    let animationgroup = CAAnimationGroup()
    animationgroup.duration = 10.0
    animationgroup.autoreverses = false
    animationgroup.repeatCount = 10000;

    animationgroup.animations = [animation, animation2]

    object.addAnimation(animationgroup, forKey: "morpher.weights")

    scene.rootNode.addChildNode(object)

Output GIF

Tried several Solutions, but I never succeeded:

  • Perhaps possible to change the ´keyPath: "morpher.weights[0]"´to ´morpher.weights´ and set the from- and toValues to something like an array. Including changing the valueFunction.

  • Because the animations happens on the presentation-layer, it must be a way to preserve already animated properties to the finished value. It tried "removedOnCompletion", but doesn't seem to work.

Has anybody a clue or a solution?

I can post a link, to the whole code, if this is necessary - don't think it is asked for here.

This is a common problem with CAAnimation - not just with SceneKit: explicit animations are removed on completion by default and the presentation value is reset to the model value (which is never modified by an explicit animation). There are 2 solutions for that:

  1. use an implicit animation instead (a SCNTransaction with a completion block that will trigger the next animation).
  2. set removedOnCompletion to NO AND set the fillMode to FillForward.

optionally for #2: you can set a delegate to your animation, and remove the animation in animationDidStop after having sync'ed the modelValue to the presentationValue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM