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

时间:2018-10-04 17:45:41

标签: ios swift scenekit trigonometry

昨天我刚刚开始学习如何使用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角应为的内容:

enter image description here

因此我将其计算为63.4 degrees,但是返回的旋转显示它应该为35.8 degrees。我的计算是否有问题,我是否不完全了解SCNVector4,还是有另一种方法可以做到这一点?

我看着Explaining in Detail the ScnVector4 method的含义是SCNVector4,但我仍然不太了解w的含义。它说w是“旋转角度”,我认为这是我认为X,Y和Z的作用。


如有任何疑问,请询问!

2 个答案:

答案 0 :(得分:2)

尽管 @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))

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

答案 1 :(得分:1)

有三种方法可以在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,弧度为结果与绕轴(-1 / √3、1 / √3、1 /√3)旋转2π/ 3相同。

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

  3. Quaternions是表达3D旋转的另一种方式(对于我们这些人来说,在本科计算机科学课程中普遍接受正规数学教育的方式,这条路甚至走得更远,但都不疯狂) )。它们具有3D图形的许多强大功能,例如易于合成和插值。在SceneKit中,simdOrientationorientation属性使您可以将节点的旋转作为四元数来使用。

    对于一个SO答案,说明四元数的工作方式太多了,但实际结果是:如果您使用的是好的矢量数学库(例如SIMD library built into iOS 9 and later),则基本上可以将它们视为不透明的—只需从最适合您的其他轮换方式中进行转换,即可获得收益。