沿世界轴旋转

时间:2017-05-25 17:14:17

标签: ios swift scenekit

我正在研究一个SceneKit项目,我想在三个轴(世界轴)上旋转一个物体但是一旦我旋转了物体,下一个旋转就会相对于新的旋转轴完成。

想象一个立方体,你应该能够使用相对于世界的三个按钮在绝对x和y和z轴上旋转。

据我所知,SCNAction有以下选项:

  • SCNAction.rotateTo(x:1.0,y:0.0,z:0.0,持续时间:0.5, usesShortestUnitArc:true)
  • SCNAction.rotateTo(x:1.0,y:0.0,z:0.0,持续时间:0.5)
  • SCNAction.rotateBy(x:1.0,y:0.0,z:0.0,持续时间:0.5)
  • SCNAction.rotate(by:0.0,around:SCNVector3,duration:0.5)
  • SCNAction.rotate(toAxisAngle:SCNVector4,持续时间:0.5)

不幸的是,这些都不是绝对的,所有这些都依赖于之前的轮换。

你知道如何实现真正的绝对世界轴旋转吗?

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:3)

要围绕世界轴旋转节点,请将节点worldTransform与旋转矩阵相乘。

我还没有找到SCNAction的解决方案,但使用SCNTransaction非常简单。

func rotate(_ node: SCNNode, around axis: SCNVector3, by angle: CGFloat, duration: TimeInterval, completionBlock: (()->())?) {
    let rotation = SCNMatrix4MakeRotation(angle, axis.x, axis.y, axis.z)
    let newTransform = node.worldTransform * rotation

    // Animate the transaction
    SCNTransaction.begin()
    // Set the duration and the completion block
    SCNTransaction.animationDuration = duration
    SCNTransaction.completionBlock = completionBlock

    // Set the new transform
    node.transform = newTransform

    SCNTransaction.commit()
}

如果节点的父节点具有不同的变换,则此方法无效,但我们可以通过将生成的变换转换为父节点坐标空间来解决此问题。

func rotate(_ node: SCNNode, around axis: SCNVector3, by angle: CGFloat, duration: TimeInterval, completionBlock: (()->())?) {
    let rotation = SCNMatrix4MakeRotation(angle, axis.x, axis.y, axis.z)
    let newTransform = node.worldTransform * rotation

    // Animate the transaction
    SCNTransaction.begin()
    // Set the duration and the completion block
    SCNTransaction.animationDuration = duration
    SCNTransaction.completionBlock = completionBlock

    // Set the new transform
    if let parent = node.parent {
        node.transform = parent.convertTransform(newTransform, from: nil)
    } else {
        node.transform = newTransform
    }

    SCNTransaction.commit()
}

您可以在this Swift Playground尝试此操作。

我希望这就是你要找的东西。