我有一个对象,它在初始化期间创建了一个几何图形。
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)
}
}
然后在我的 View Controller 中,我将它添加到节点树中。
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
。在这种情况下我应该怎么做?
最佳答案
每帧重建一个顶点数组并没有那么糟糕。然而,每帧将其重新上传到 GPU 可能不会带来让您的一天变得愉快的性能。
相反,我建议使用 shader modifiers在 GPU 的顶点阶段自定义您的几何图形。 (请务必点击该页面顶部的“更多”链接以进行全面讨论。)您甚至可以将其与自定义 Helix
类结合使用,以更改宽度/半径/间距等Swift 中的参数既好又简单——实现 SCNShadable
的 SceneKit 对象自动使用 KVO 让您将 GLSL 制服视为类属性。
为此,您首先需要重构,以便 Helix
成为 SCNGeometry
或 SCNNode
的子类,然后,就像在 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 */
最后,使用 SCNShaderModifierEntryPointGeometry
入口点将此代码段分配给节点的 shaderModifiers
:
let shader = "all that GLSL stuff above" // or better, load it from a file
geometry.shaderModifiers = [ SCNShaderModifierEntryPointGeometry: shader ]
此时,您应该能够创建自定义 Helix 节点/几何体的实例,并使用 SceneKit 的任何动画技巧为其 width
、height
设置动画,等属性。
关于cocoa-touch - 如何为 SCNNode 上的自定义属性设置动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27281755/