【问题标题】:Is it possible to calculate a sine of timeline's `Time`variable in SceneKit?是否可以在 SceneKit 中计算时间线的“时间”变量的正弦值?
【发布时间】:2018-10-29 15:52:48
【问题描述】:

对于 3D 立方体,我需要沿 X 轴进行乒乓​​运动。所以我将三角函数sine 应用于time 变量的x 参数。但是没有乒乓运动,只有标量运动。

任何帮助表示赞赏!

override func awakeFromNib() {
    super.awakeFromNib()

    .......

    //CFTimeInterval derived by calling `mach_absolute_time()` and converting the result to seconds.
    let t = CACurrentMediaTime()

    animation.toValue = NSValue(SCNVector3: SCNVector3(x: CGFloat(sin(t)*5), 
                                                       y: CGFloat(0), 
                                                       z: CGFloat(0)))

    animation.duration = 60
    animation.repeatCount = MAXFLOAT    
    cube.addAnimation(animation, forKey: nil)
}

【问题讨论】:

    标签: swift macos scenekit trigonometry


    【解决方案1】:

    以下代码的问题在于它是在动画实例化时执行的,而不是在动画求值时执行的。那就是sin(t) 的值永远不会随着时间而改变。它被评估一次,结果将是线性插值的最终值。

    let t = CACurrentMediaTime()
    animation.toValue = NSValue(SCNVector3: SCNVector3(x: CGFloat(sin(t)*5), 
                                                       y: CGFloat(0), 
                                                       z: CGFloat(0)))
    

    相反,CAAnimation 类公开了您可能想要的 timingFunction 属性。

    【讨论】:

    • 最终起搏可以达到同样的效果。看看kCAMediaTimingFunctionEaseInEaseOut:«Ease-in-ease-out pacing,它会导致动画开始缓慢,在其持续时间的中间加速,然后在完成之前再次减速。»
    • timingFunction 是关于曲线的插值(预定义曲线的轮廓,如 kCAMediaTimingFunctionLinearkCAMediaTimingFunctionEaseInEaseOut)。这与sine wavefrequency、正/负部分、offsetamplitude 无关。
    【解决方案2】:

    可以在 SceneKit 中计算时间线时间的正弦值。为此,我需要为 SCNAction 创建一个扩展名(在 Swift 4.1 中):

    let pi = CGFloat(Double.pi)
    
    extension SCNAction {
    
        static func oscillation(amplitude a: CGFloat, 
                               timePeriod t: CGFloat) -> SCNAction {
    
            let action = SCNAction.customAction(duration: Double(t)) { node, currentTime in
                let offset = a * sin(2 * pi * currentTime / t)
                node.position.x = offset
            }
            return action
        }
    }
    
    class GameViewController: NSViewController, SCNSceneRendererDelegate {
    
        let box = SCNNode()
        // ..................
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // ..................
            box.geometry = SCNBox()
            scene.rootNode.addChildNode(box)
    
            let oscillate = SCNAction.oscillation(amplitude: 4, timePeriod: 1)
            box.runAction(SCNAction.repeatForever(oscillate))
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-24
      • 2013-02-03
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多