在 SceneKit 中更改 "field of view"
Change "field of view" in SceneKit
我有一些带透视投影的相机和 (0,0,0) 中的对象。
我根据这个相机计算了这个对象的"bounding frame"(屏幕上的像素大小)并缩放它以适应屏幕大小。现在它在屏幕中间。
scnView 的框架等于屏幕大小,我在这个视图上方有一些 UI 组件(例如导航栏和视图底部的一些大透明视图)。 scnView 有一些全屏背景,这个对象可以是 scaled/moved/... 因此我需要 scnview 是全屏的。
然后我将这个对象移动到 "clear area" 的中间(没有 UI 组件的区域)并看到这个对象的底部(好像它在我上方),因为我的投影是透视。
我想把这个物体移动到清晰区域的中心,看起来就像它在我面前一样,没有任何失真。我怎样才能做到这一点?
我看到 2 个解决方案。
1)在纹理中将我的对象绘制在屏幕外,然后在屏幕上所需位置绘制该纹理。
2)创建 scnView 高一点。例如,将帧大小设置为 = (0, (bottomHeight - topHeight) / 2, width, height + (bottomHeight - totopHeight) / 2) 以将 scnView 的中心移动到所需位置。
但我不喜欢第一个解决方案,因为添加了绘图调用,第二个解决方案甚至听起来很糟糕。
P.S。对不起那些照片
更新: 基本上我想使用透视投影并在 SceneKit 中像移动 2D 图像一样移动 3D 对象。
抱歉,如果我没有理解正确,但是你能把相机向上扫射并居中吗,还是不够清楚?
func strafeY(vAmount: XFloat)
{
nPosition = cgVecAdd(v1: nPosition, v2: cgVecScalarMult(v: nTarget, s: vAmount))
}
试试这个...生成一个新的 scenekit 游戏项目,然后用下面的代码替换默认旋转。
移动物体时稍微旋转 X 以 "somewhat" 保持与眼睛的关系。
您可以创建一个类似但独立的例程来执行较小的增量以使其平滑。
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)
通过更改相机投影变换解决了它。像:
let newMatrix = SCNMatrix4Mult(initialProjectionCameraMatrix, translationMatrix)
我有一些带透视投影的相机和 (0,0,0) 中的对象。 我根据这个相机计算了这个对象的"bounding frame"(屏幕上的像素大小)并缩放它以适应屏幕大小。现在它在屏幕中间。
scnView 的框架等于屏幕大小,我在这个视图上方有一些 UI 组件(例如导航栏和视图底部的一些大透明视图)。 scnView 有一些全屏背景,这个对象可以是 scaled/moved/... 因此我需要 scnview 是全屏的。
然后我将这个对象移动到 "clear area" 的中间(没有 UI 组件的区域)并看到这个对象的底部(好像它在我上方),因为我的投影是透视。
我想把这个物体移动到清晰区域的中心,看起来就像它在我面前一样,没有任何失真。我怎样才能做到这一点?
我看到 2 个解决方案。 1)在纹理中将我的对象绘制在屏幕外,然后在屏幕上所需位置绘制该纹理。 2)创建 scnView 高一点。例如,将帧大小设置为 = (0, (bottomHeight - topHeight) / 2, width, height + (bottomHeight - totopHeight) / 2) 以将 scnView 的中心移动到所需位置。
但我不喜欢第一个解决方案,因为添加了绘图调用,第二个解决方案甚至听起来很糟糕。
P.S。对不起那些照片
更新: 基本上我想使用透视投影并在 SceneKit 中像移动 2D 图像一样移动 3D 对象。
抱歉,如果我没有理解正确,但是你能把相机向上扫射并居中吗,还是不够清楚?
func strafeY(vAmount: XFloat)
{
nPosition = cgVecAdd(v1: nPosition, v2: cgVecScalarMult(v: nTarget, s: vAmount))
}
试试这个...生成一个新的 scenekit 游戏项目,然后用下面的代码替换默认旋转。
移动物体时稍微旋转 X 以 "somewhat" 保持与眼睛的关系。
您可以创建一个类似但独立的例程来执行较小的增量以使其平滑。
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)
通过更改相机投影变换解决了它。像:
let newMatrix = SCNMatrix4Mult(initialProjectionCameraMatrix, translationMatrix)