【问题标题】:Rotation along world axis沿世界轴旋转
【发布时间】:2017-10-26 10:32:01
【问题描述】:

我正在处理一个 SceneKit 项目,我想在三个轴(世界轴)上旋转一个对象,但是一旦我旋转了对象,下一次旋转是相对于新的旋转轴完成的。

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

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

  • SCNAction.rotateTo(x: 1.0, y: 0.0, z: 0.0, 持续时间: 0.5, 使用ShortestUnitArc: 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)

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

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

提前感谢您的帮助!

【问题讨论】:

    标签: ios swift scenekit


    【解决方案1】:

    要绕世界轴旋转节点,请将节点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()
    }
    

    你可以在thisSwift Playground 试试这个。

    我希望这就是你要找的。​​p>

    【讨论】:

    • 谢谢 Orangenkopf,好主意!
    • 如果父母的位置不是(0,0,0),这是否也适用?当我尝试这种方法时,节点围绕父轴而不是沿着它自己的(转换后的)轴旋转 - 我错过了什么吗?
    • let newTransform = node.worldTransform * rotation 在 Swift 4 中产生错误。替换为 let newTransform = SCNMatrix4Mult(node.worldTransform, rotation)
    猜你喜欢
    • 2013-02-06
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多