如何在SCNNode上设置自定义属性的动画?

时间:2014-12-03 21:14:20

标签: cocoa-touch swift scenekit

我有一个对象,在初始化期间创建一个几何体。

class Helix {
    var width: GLfloat      // x
    var height: GLfloat     // y
    var depth: GLfloat      // z
    var radius: GLfloat
    var pitchInherent: GLfloat
    var pitchCurrent: GLfloat
    /* Other SceneKit related properties used later */
    init(width: Float, height: Float, depth: Float) {
        /* Geometry logic */
        geometry = SCNGeometry(sources: [vertexSource], elements: [element])
    }
    func getNode() -> SCNNode {
        return SCNNode(geometry: geometry)
    }
}

然后在我的视图控制器中,我将它添加到节点树。

let scene = SCNScene()
let helix = Helix(width: 30, height: 30, depth: 30)
let helixNode = helix.getNode()
scene.rootNode.addChildNode(helixNode)

我想为pitchCurrent属性设置动画。在自定义Objective-C对象的CALayer世界中,我曾经将我想要设置为动态的属性dynamic指定为适当的key指定了一个侦听器。在这种情况下我该怎么做?

1 个答案:

答案 0 :(得分:2)

每帧重建一个顶点数组并不是那么糟糕。但是,每帧重新上传到GPU,可能不会带来让您的一天变亮的性能。

相反,我建议使用shader modifiers在GPU的顶点阶段自定义几何体。 (请务必点击该页面顶部的"更多"链接进行详细讨论。)您甚至可以将其与自定义Helix课程结合使用,以更改宽度/半径/音高来自Swift的/ etc参数很简单 - 实现SCNShadable的SceneKit对象自动使用KVO让你将GLSL制服视为类属性。

要执行此操作,您首先需要重构,以便Helix子类SCNGeometrySCNNode,然后,就像在CALayer情况下一样,声明您的属性为dynamic

然后,创建一个执行几何自定义的GLSL片段:

// declare uniforms whose names match your class' dynamic properties
uniform float width;
uniform float height;
// etc

// do your geometry math 
_geometry.position = /* Geometry logic */

最后,使用shaderModifiers入口点将此代码段分配给您的节点的SCNShaderModifierEntryPointGeometry

let shader = "all that GLSL stuff above" // or better, load it from a file
geometry.shaderModifiers = [ SCNShaderModifierEntryPointGeometry: shader ]

此时,您应该能够创建自定义Helix节点/几何的实例,并使用SceneKit的任何动画技巧来为其widthheight等属性设置动画。