Morphing between 3D Objects using IOS SceneKit

I am rendering a 3D object in an IOS application using

SceneKit
. I have another 3D object. How do I morph the geometry of the first 3D object into the geometry of the second 3D object?


Is there a way to accomplish such a transition?


I looked at

SCNMorpher
. The documentation says it is
An object that manages smooth transitions between a node's base geometry and one or more target geometries
. This sounds promising, however, what if I have
n
3D objects and I want to morph between any pair of them. Can I set what is the base geometry and what is the target geometry at runtime?

Replies

Hello,


There are several caveats to the SCNMorpher.


Most importantly:


"The base geometry and all target geometries must be topologically identical—that is, they must contain the same number and structural arrangement of vertices."


So, you cannot morph between completely unrelated geometries using SCNMorpher.


You asked:

"what if I have

n
3D objects and I want to morph between any pair of them. Can I set what is the base geometry and what is the target geometry at runtime?"


The base geometry is always going to be the SCNNode's .geometry.


You can set weights for a specific target using the setWeight(_:forTargetAt:) method. The range in weight for each target goes from 0 to 1.


Here is a very basic example which morphs between two SCNBox geometries of different size:


let baseGeometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
baseGeometry.firstMaterial?.diffuse.contents = UIColor.red
let targetGeometry = SCNBox(width: 5, height: 5, length: 5, chamferRadius: 0)
        
let node = SCNNode(geometry: baseGeometry)
        
let morpher = SCNMorpher()
morpher.targets = [targetGeometry]
        
node.morpher = morpher
        
let animation = CABasicAnimation(keyPath: "morpher.weights[0]")
animation.fromValue = 0.0;
animation.toValue = 1.0;
animation.autoreverses = true;
animation.repeatCount = .infinity;
animation.duration = 5;
node.addAnimation(animation, forKey: nil)
        
scene.rootNode.addChildNode(node)