Matthew Anguelo
Matthew Anguelo

Reputation: 293

SceneKit - How to Add Animations to Change SCNNode's Color?

I would like to know how I can animate an SCNNode's color using Swift.

For example: I would like the node to constantly be changing color or I would like the node to fade from black to blue.

Do I use the SCNAction fadeIn or fadeOut?

Upvotes: 9

Views: 4789

Answers (3)

Hope
Hope

Reputation: 2326

I am using this function; You just give name of material, how long animation will take and current color and the which color will be reached.

You give color as arrays (red, green, blue and alpha);

 let startColor: [CGFloat] = [0.5, 0.5, 1, 1]
 let targetColor: [CGFloat] = [1, 1, 1, 1]

This is how you call function;

   changeColorWithAnimation(duration    : 5,
                            materialName: myCubeMaterial,
                            start       : startColor,
                            end         : targetColor)






 func chageColorWithAnimation(duration: CGFloat,
                                     materialName: SCNMaterial,
                                     start: [CGFloat],
                                     end: [CGFloat]){

    let rs = (end[0] - start[0]) / duration
    let gs = (end[1] - start[1]) / duration
    let bs = (end[2] - start[2]) / duration
    let alphas = (end[3] - start[3]) / duration


    let changeColor = SCNAction.customAction(duration: TimeInterval(duration)) { (node, elapsedTime) -> () in

        let red = start[0] + rs * elapsedTime 
        let green = start[1] + gs * elapsedTime 
        let blue = start[2] + bs * elapsedTime 
        let alpha = start[3] + alphas * elapsedTime

        materialName.diffuse.contents = UIColor(displayP3Red:red,
                                                green: green,
                                                blue: blue,
                                                alpha: alpha)
    }
    rootNode.runAction(changeColor)
}

Upvotes: 0

Tony
Tony

Reputation: 1611

Got idea from @Luca Angeletti, I write the code so we can animate between any colors, include their alphas:

func aniColor(from: UIColor, to: UIColor, percentage: CGFloat) -> UIColor {
    let fromComponents = from.cgColor.components!
    let toComponents = to.cgColor.components!

    let color = UIColor(red: fromComponents[0] + (toComponents[0] - fromComponents[0]) * percentage,
        green: fromComponents[1] + (toComponents[1] - fromComponents[1]) * percentage,
        blue: fromComponents[2] + (toComponents[2] - fromComponents[2]) * percentage,
        alpha: fromComponents[3] + (toComponents[3] - fromComponents[3]) * percentage)
    return color
}

Use:

let oldColor = UIColor.red
let newColor = UIColor(colorLiteralRed: 0.0, green: 0.0, blue: 1.0, alpha: 0.5)
let duration: TimeInterval = 1
let act0 = SCNAction.customAction(duration: duration, action: { (node, elapsedTime) in
    let percentage = elapsedTime / CGFloat(duration)
    node.geometry?.firstMaterial?.diffuse.contents = self.aniColor(from: newColor, to: oldColor, percentage: percentage)
})
let act1 = SCNAction.customAction(duration: duration, action: { (node, elapsedTime) in
    let percentage = elapsedTime / CGFloat(duration)
    node.geometry?.firstMaterial?.diffuse.contents = self.aniColor(from: oldColor, to: newColor, percentage: percentage)
})

let act = SCNAction.repeatForever(SCNAction.sequence([act0, act1]))
node.runAction(act)

Upvotes: 11

Luca Angeletti
Luca Angeletti

Reputation: 59506

You can create a custom action.

If you have a red sphere in your scene

let sphereNode = scene.rootNode.childNode(withName: "sphere", recursively: false)!
sphereNode.geometry!.firstMaterial!.diffuse.contents = UIColor.red

This is how you build the custom action

let changeColor = SCNAction.customAction(duration: 10) { (node, elapsedTime) -> () in
    let percentage = elapsedTime / 5
    let color = UIColor(red: 1 - percentage, green: percentage, blue: 0, alpha: 1)
    node.geometry!.firstMaterial!.diffuse.contents = color
}

Finally you just need to run the action on the sphere

sphereNode.runAction(changeColor)

Result

enter image description here

Upvotes: 20

Related Questions