【问题标题】:Change "field of view" in SceneKit在 SceneKit 中更改“视野”
【发布时间】:2018-10-17 16:55:48
【问题描述】:

我有一些带有透视投影的相机和 (0,0,0) 中的对象。 我根据这个相机计算了这个对象的“边界框”(屏幕上的像素大小)并缩放它以适应屏幕大小。现在它在屏幕中间。

scnView 的框架等于屏幕大小,我在这个视图上方有一些 UI 组件(例如导航栏和视图底部的一些大透明视图)。 scnView 有一些全屏背景,这个对象可以缩放/移动/...因此我需要 scnview 全屏。

然后我将这个对象移动到“透明区域”(没有 UIComponents 的区域)的中间并看到这个对象的底部(好像它在我的上方),因为我的投影是透视的。

我想把这个物体移动到清晰区域的中心,让它看起来像在我面前,没有任何扭曲。我怎样才能做到这一点?

我看到了 2 个解决方案。 1)在纹理中将我的对象绘制到屏幕外,然后在屏幕上所需位置绘制此纹理。 2)创建 scnView 高一点。例如将 frame size 设置为 = (0, (bottomHeight - topHeight) / 2, width, height + (bottomHeight - topHeight) / 2) 以将 scnView 的中心移动到所需位置。

但我不喜欢第一个解决方案,因为添加了绘制调用,第二个解决方案甚至听起来很糟糕。

附注对不起那些照片

更新:基本上我想使用透视投影并像 SceneKit 中的 2D 图像一样移动 3D 对象。

【问题讨论】:

    标签: ios scenekit scnnode scncamera


    【解决方案1】:

    通过改变相机投影变换解决了这个问题。喜欢:

    let newMatrix = SCNMatrix4Mult(initialProjectionCameraMatrix, translationMatrix)
    

    【讨论】:

      【解决方案2】:

      试试这个...生成一个新的场景包游戏项目,然后用下面的代码替换默认旋转。

      将对象向上移动时稍微旋转 X,以“稍微”保持与眼睛的关系。

      您可以创建一个类似但单独的例程来执行较小的增量以使其平滑。

          ship.runAction(SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(-90)), y: 0, z: 0, duration: 0))
      
          let vRotateAmount: Float = 3
      
          let vAction1 =  SCNAction.move(to: SCNVector3Make(0, 1, 0), duration: 1)
          let vAction1a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(vRotateAmount)), y:0, z:0, duration: 1)
      
          let vAction2 = SCNAction.move(to: SCNVector3Make(0, 2, 0), duration: 1)
          let vAction2a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(vRotateAmount)), y:0, z:0,  duration: 1)
      
          let vAction3 =  SCNAction.move(to: SCNVector3Make(0, 1, 0), duration: 1)
          let vAction3a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(-vRotateAmount)), y:0, z:0,  duration: 1)
      
          let vAction4 = SCNAction.move(to: SCNVector3Make(0, 0, 0), duration: 1)
          let vAction4a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(-vRotateAmount)), y:0, z:0,  duration: 1)
      
          let seq = SCNAction.sequence([vAction1, vAction1a, vAction2, vAction2a, vAction3, vAction3a, vAction4, vAction4a])
          let allSeq = SCNAction.repeatForever(seq)
          ship.runAction(allSeq)
      

      【讨论】:

        【解决方案3】:

        抱歉,如果我的理解不正确,您可以将相机扫射并居中吗?还是不够清楚?

        func strafeY(vAmount: XFloat)
        {
          nPosition = cgVecAdd(v1: nPosition, v2: cgVecScalarMult(v: nTarget, s: vAmount))
        }
        

        【讨论】:

        • 我不太明白你的建议是什么。目前我有一个指向物体的相机。例如它在视图的中心。我想把这个对象放在视图的顶部,但没有任何失真。换句话说:我想为我的对象创建 2 种类型的移动:1)标准用 1 个手指,如 3d(当我向下移动对象时,我看到对象的顶面)2)另一种用 2 个手指,如2d(当我向下移动这个对象时,我看到了相同的图像)。
        • 好的 - 一旦你在 3D 中移动东西(Scenekit),正如你所看到的 - 事情会改变。一种选择是让 2D 对象表现得像一个广告牌。在您的对象上设置 SCNLookAtConstraint 并始终将其指向相机。这应该对一些人有所帮助,但我认为最终结果不会是你想要的。如果它真的需要表现得像一个 2D 对象,那么你可以在 Scenekit 的顶部运行 SpriteKit 并使用覆盖。可以左右上下移动,视角不变。
        • 是的,但我想要同一对象的展位行为。例如,我在中心有一个对象。我想将它像图像一样向上移动 100 像素,然后像 3D 模型一样在新位置旋转它。
        猜你喜欢
        • 2017-01-11
        • 1970-01-01
        • 2015-02-19
        • 2014-08-09
        • 2016-06-14
        • 2020-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多