视口?或相机?视野?旋转 iOS 设备的变化

Viewport? or Camera? of Field of View? changes on rotating iOS device

我在我的应用程序中使用 SceneKit 视图创建了一个 3d 世界。

我需要支持所有 iOS 设备和方向。

我不懂 3d 数学、矩阵,也不懂相机之类的东西,但我已经构建了一个 3d 世界,并且我有一个可以工作的相机,并使用 Pan Gesture 围绕着物体的中心旋转世界。

我的问题是,当我将设备从纵向旋转到横向时,SceneKit 视图会自动改变它的视角(我不确定 - 相机?还是世界本身?)和看起来像它的对象曾经很近,现在又回到了远方。

我想要发生的是,不管 'viewport' 旋转如何?还是相机?还是世界观?保持不变,并且相机与物体的距离没有 "look" 不同,即物体在视觉上停留在同一个地方。

我没有做过任何矩阵操作或设置任何复杂的东西。

我知道 SceneKit 的单位是米,所以我的对象大小正确,相机距它的米数正确...看起来 'correct'

我不明白的是为什么这一切都变了风景。

是的,SceneKit 视图正在使用 AutoLayout 约束来包围屏幕的边缘。

这是我的相机设置:

private func setupCamera() -> SCNNode {
    let camera = SCNCamera()
    camera.usesOrthographicProjection = false
    camera.orthographicScale          = 9
    camera.zNear                      = 0.01
    camera.zFar                       = 9500
    camera.focalLength                = 50
    camera.focusDistance              = 33
    camera.fieldOfView                = 100
    let cameraNode                    = SCNNode()
    cameraNode.position               = SCNVector3(x:0, y:0, z: 500.0)
    cameraNode.camera                 = camera
    self.cameraNode                   = cameraNode
    let cameraOrbit                   = SCNNode()

    cameraOrbit.addChildNode(self.cameraNode!)

    return cameraOrbit
}

我发现 'fix' 的唯一方法是使 SceneKit 视图始终为正方形且大小始终为最大的设备宽度或高度并保持在屏幕的中心中心.

但是这种方法不适用于应用程序的其他部分,所以我知道我需要这样做 'properly'。

所以有人可以提供代码或告诉我我需要了解什么以便在设备旋转时调用的函数中,即 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 然后我可以更正此自动更改并保持视图的 'perspective'一样。

谢谢。

在玩了 4 天约束、手动移动框架和各种东西之后,我已经修复了它。

我用 0 个常量将 scenekitview 约束到 superview,所以它始终是屏幕的大小。

那么我只需要一行就可以解决这个问题……唉。

我只需要将 'sensorHeight' 减半,然后效果就很好了。

if UIDevice.current.orientation == .landscapeLeft  || 
   UIDevice.current.orientation == .landscapeRight
{
    self.cameraNode?.camera?.sensorHeight  = 12
}
else
{
    self.cameraNode?.camera?.sensorHeight  = 24
}

编辑:

由于屏幕尺寸的限制,默认视野意味着您有鱼眼效果。

将 FoV 降低到几乎一半解决了这个问题,现在对象旋转时没有扭曲:

    camera.fieldOfView = 50

从ios11你也可以告诉scenekit使用哪个投影。

这为我解决了这个问题并且与纵横比无关。

camera.projectionDirection = isPortrait ? .vertical : .horizontal