如何将相机指向 iOS 11 以下的 SCNVector3 点

How to point the camera towards a SCNVector3 point below iOS 11

我昨天才开始学习如何使用 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 是 roll...?)

这是我为重现我认为的 Y 角 应该做的工作:

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

我看了Explaining in Detail the ScnVector4 method是什么SCNVector4,但我还是不太明白w是什么。它说 w 是 'angle of rotation',我认为 X、Y 和 Z 的用途。


有什么问题欢迎提问!

在 SceneKit 中可以通过三种方式来表达 3D 旋转:

  1. 您在纸上所做的是计算围绕 x、y 和 z 轴的不同角度。这些被称为 Euler angles, or pitch, yaw, and roll. You might get results that more resemble your hand-calculations if you use eulerAngles or simdEulerAngles 而不是“旋转”。 (或者你可能不会,因为欧拉角系统的困难之一是你必须以正确的顺序应用这三个旋转中的每一个。)

  2. simdRotation or rotation uses a four-component vector (float4 or SCNVector4) to express an axis-angle representation的轮换。这依赖于一些对于许多 3D 图形新手来说并不明显的数学知识:围绕不同轴的任何旋转序列的结果都可以最低限度地表示为围绕新轴的单次旋转。

    For example, a rotation of π/2 radians (90°) around the z-axis (0,0,1) followed by a rotation of π/2 around the y-axis (0,1,0) has the same result as a rotation of 2π/3 around the axis (-1/√3, 1/√3, 1/√3).

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

  3. Quaternions are another way to express 3D rotation (and one that's even further off the beaten path for those of us with the formal math education common to undergraduate computer science curricula, but not crazy advanced, either). These have lots of great features for 3D graphics, like being easy to compose and interpolate between. In SceneKit, the simdOrientationorientation 属性 让您可以将节点的旋转作为四元数处理。

    解释四元数的工作原理对于一个 SO 答案来说太多了,但实际结果是这样的:如果你正在使用一个好的矢量数学库(比如 SIMD library built into iOS 9 and later),你基本上可以处理它们作为不透明 — 只需从对您来说最简单的其他旋转表示形式进行转换,即可获得收益。

虽然@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))

希望这对以后的人有所帮助!