0

I am using Apple's SceneKit to render a tube which consists of 50 triangle strips as illustrated here: enter image description here

I want to animate a "growing" tube by using the primitiveRange property.

let tube = createTube() // create's tube.geometry which has 50 elements
let tubeNode = SCNNode(geometry: tube.geometry)
...
let animation = CABasicAnimation(keyPath: "geometry.elements[0].primitiveRange")
animation.fromValue = NSValue(range: NSRange(location: 0, length: 0))
animation.toValue = NSValue(range: NSRange(location: 0, length: tube.geometry.elements.count))
animation.duration = 5
animation.repeatCount = Float.infinity
tubeNode.geometry?.addAnimation(animation, forKey: "don't care")

scene.rootNode.addChildNode(tubeNode)

Nothing is animating (I simply see the full tube above) and I am not getting any warnings on the console. If I change the key "geometry.elements.primitiveRange" to "foo" I do get the following warning on the console

 ExtrudedTube[98737:24354579] [SceneKit] Error: _C3DModelPathResolverRegistryResolvePathWithClassName unknown path (
    foo
)

Perhaps this property is not animatable? I don't see documentation that says it is or isn't. Any idea how to create the "growing tube" animation using this mesh in SceneKit?

wcochran
  • 10,089
  • 6
  • 61
  • 69
  • where are you getting that key from? [appendix B and C here](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/AnimatableProperties/AnimatableProperties.html#//apple_ref/doc/uid/TP40004514-CH11-SW1) list available CA animatable properties – Fault Jan 29 '23 at 18:41
  • @Fault In the Apple doc example at https://developer.apple.com/documentation/scenekit/animation/animating_scenekit_content they animating using the key `extrude`. Thus I am assuming the animatable properties are extended beyond the usual view / layer based classes. – wcochran Feb 02 '23 at 18:32
  • yes excellent point. (or technically the key `geometry.extrusionDepth`). so the aforementioned appendix B and C are not definitive it seems. would be nice to have better documentation about which keys are available. did you see [this trick](https://stackoverflow.com/a/48792390/3680644) for using autocomplete to probe for potential keys? won't guarantee that the key is *implemented* but might help – Fault Feb 02 '23 at 20:43
  • @Fault autocompletion will give me `#keyPath(SCNNode.geometry.elements.primitiveRange)` , but the problem is that `elements` is an array -- the first element (`elements[0]`) is the one I want to animate. – wcochran Feb 03 '23 at 23:56

1 Answers1

0

I was never able to pull off the animation using the "keypath" (I think there probably is a way to do it, but there is no documentation on the details). I can use SCNAction though it it works well:

if let numPrimitives = tubeNode.geometry?.elements[0].primitiveCount {
    tubeNode.geometry?.elements[0].primitiveRange = NSRange(location: 0, length: 0)
    let duration : Double = 5.0
    let growTube = SCNAction.customAction(duration: duration, action: {node, elapsedTime in
        let f = Double(elapsedTime)/duration
        let n = Int(f*Double(numPrimitives))
        node.geometry?.elements[0].primitiveRange = NSRange(location: 0, length: n)
    })
    tubeNode.runAction(growTube)
}
wcochran
  • 10,089
  • 6
  • 61
  • 69