【问题标题】:How to point the camera towards a SCNVector3 point below iOS 11如何将相机指向 iOS 11 以下的 SCNVector3 点
【发布时间】:2018-10-04 17:45:41
【问题描述】:

我昨天刚开始学习如何使用SceneKit,所以我可能会弄错或不正确的东西。我试图让我的cameraNode 看到场景中的SCNVector3 点。

我正在尝试向iOS 11.0 以下的人提供我的应用程序。但是,look(at:) 函数仅适用于iOS 11.0+

这是我初始化相机的函数:

func initCamera() {
    cameraNode = SCNNode()
    cameraNode.camera = SCNCamera()
    cameraNode.position = SCNVector3(5, 12, 10)
    if #available(iOS 11.0, *) {
        cameraNode.look(at: SCNVector3(0, 5, 0)) // Calculate the look angle
    } else {
        // How can I calculate the orientation? <-----------
    }
    print(cameraNode.rotation) // Prints: SCNVector4(x: -0.7600127, y: 0.62465125, z: 0.17941462, w: 0.7226559)
    gameScene.rootNode.addChildNode(cameraNode)
}

SCNVector4(x: -0.7600127, y: 0.62465125, z: 0.17941462, w: 0.7226559) 的度数方向是x: -43.5, y: 35.8, z: 10.3,我看不懂w。 (另外,为什么不是z = 0?我以为z 是滚动...?)

这是我重新创建我认为的 Y 角 应该是什么的工作:

所以我算出它是63.4 degrees,但返回的旋转显示它应该是35.8 degrees。是不是我的计算有问题,我是不是完全看不懂SCNVector4,还是有其他方法可以做到这一点?

我查看了Explaining in Detail the ScnVector4 methodSCNVector4 是什么,但我仍然不明白w 是什么。它说w 是“旋转角度”,我认为这就是我认为 X、Y 和 Z 的用途。


如果您有任何问题,请提出!

【问题讨论】:

    标签: ios swift scenekit trigonometry


    【解决方案1】:

    虽然 @rickster 已经给出了节点属性的解释,但我已经想出了一种方法来旋转节点以使用数学(三角学)查看一个点。

    这是我的代码:

    // Extension for Float
    extension Float {
        /// Convert degrees to radians
        func asRadians() -> Float {
            return self * Float.pi / 180
        }
    }
    

    还有:

    // Extension for SCNNode
    extension SCNNode {
        /// Look at a SCNVector3 point
        func lookAt(_ point: SCNVector3) {
            // Find change in positions
            let changeX = self.position.x - point.x // Change in X position
            let changeY = self.position.y - point.y // Change in Y position
            let changeZ = self.position.z - point.z // Change in Z position
    
            // Calculate the X and Y angles
            let angleX = atan2(changeZ, changeY) * (changeZ > 0 ? -1 : 1)
            let angleY = atan2(changeZ, changeX)
    
            // Calculate the X and Y rotations
            let xRot = Float(-90).asRadians() - angleX // X rotation
            let yRot = Float(90).asRadians() - angleY // Y rotation
            self.eulerAngles = SCNVector3(CGFloat(xRot), CGFloat(yRot), 0) // Rotate
        }
    }
    

    你调用函数使用:

    cameraNode.lookAt(SCNVector3(0, 5, 0))
    

    希望这对未来的人们有所帮助!

    【讨论】:

    • 是的,这行得通。还要注意,如果动画持续时间为零,SCNAction.rotateTo 相当于直接设置eulerAngles
    【解决方案2】:

    在 SceneKit 中有三种表达 3D 旋转的方式:

    1. 您在纸上所做的是计算围绕 x、y 和 z 轴的单独角度。这些称为Euler angles,或俯仰、偏航和滚动。如果您使用 eulerAnglessimdEulerAngles 而不是 `rotation. (或者您可能不会,因为欧拉角系统的困难之一是您必须以正确的顺序应用这三个旋转中的每一个。)

    2. simdRotationrotation 使用四分量向量(float4SCNVector4)来表示旋转的 axis-angle representation。这依赖于一些数学,这对于许多 3D 图形的新手来说并不明显:围绕不同轴的任何旋转序列的结果可以最低限度地表示为围绕新轴的单个旋转。

      例如,围绕 z 轴 (0,0,1) 旋转 π/2 弧度 (90°),然后围绕 y 轴 (0,1,0) 旋转 π/2与绕轴旋转 2π/3 (-1/√3, 1/√3, 1/√3) 的结果相同。

      这就是你对 SceneKit rotation 向量的 x、y、z 和 w 分量感到困惑的地方——前三个分量是长度,表示 3D 向量,而第四个是围绕该向量的弧度旋转。

    3. Quaternions 是表达 3D 旋转的另一种方式(对于我们这些接受本科计算机科学课程常见的正规数学教育的人来说,这种方式更离谱,但也不是疯狂的高级)。这些具有许多 3D 图形的强大功能,例如易于组合和插值。在 SceneKit 中,simdOrientationorientation 属性可让您将节点的旋转作为四元数。

      解释四元数的工作原理对于一个 SO 答案来说太过分了,但实际的结果是:如果您正在使用一个好的向量数学库(如 SIMD library built into iOS 9 and later),您基本上可以将它们视为不透明的 - 只是从对您来说最容易的任何其他旋转表示进行转换,并获得好处。

    【讨论】:

      猜你喜欢
      • 2019-06-07
      • 1970-01-01
      • 2018-03-02
      • 2012-11-19
      • 2014-07-29
      • 2019-09-05
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多