我正在尝试确定SCNCamera的不同Z深度处的世界坐标空间的宽度。据我了解,Z值为0是近平面,而1则是远平面。
再次,我的理解是截头锥体是一个倒置的方形金字塔,其顶点位于SCNCamera。
让我失望的是,我获得的宽度不是线性的,而是随着我接近Z = 1而呈指数形式。对我来说,这与我将视锥作为正方形的心理形状相反金字塔。
这是示例操场代码:
import UIKit
import SceneKit
import PlaygroundSupport
let scene = SCNScene()
let leftCamera = SCNCamera()
let leftCameraNode = SCNNode()
let boxGeometry = SCNBox(width: 10, height: 10, length: 10, chamferRadius: 1.0)
let box = SCNNode(geometry: boxGeometry)
box.position = SCNVector3(0,0,0)
scene.rootNode.addChildNode(box)
scene.rootNode.addChildNode(leftCameraNode)
leftCameraNode.position = SCNVector3(0, 0, 50)
leftCameraNode.eulerAngles = SCNVector3(0, 0, 0)
leftCameraNode.camera = leftCamera
let leftCameraView = SCNView(frame: CGRect(x: 0, y: 0, width: 700, height: 500))
PlaygroundPage.current.liveView = leftCameraView
leftCameraView.scene = scene
leftCameraView.autoenablesDefaultLighting = true
leftCameraView.pointOfView = leftCameraNode
var widths = [CGFloat : Float]()
func widthForDepth(_ depth: CGFloat) {
let topLeftUnprojectedPoint = leftCameraView.unprojectPoint(SCNVector3(0, 0, depth))
let topRightUnprojectedPoint = leftCameraView.unprojectPoint(SCNVector3(leftCameraView.bounds.width, 0, depth))
let width = topRightUnprojectedPoint.x - topLeftUnprojectedPoint.x
widths[depth] = width
}
widthForDepth(0)
widthForDepth(0.5)
widthForDepth(0.75)
widthForDepth(0.9)
widthForDepth(0.95)
widthForDepth(1)
这使我在不同深度获得了以下值: Z = 0-> 1.61
Z = 0.5-> 3.2
Z = 0.75-> 6.2
Z = 0.9-> 14.8
Z = 0.95-> 27.1
Z = 1-> 161.6
我的理解是Z = 1的这个值是正确的,但是其他值对我来说似乎没有意义。
“我的盒子”的大小为10个单位,适合相机深度值为0.5的屏幕(对于zFar为100且zNear为1的相机,距离为50个单位)。但是,当非投影计算显示屏幕为3.2单位宽(0.5)时,它在屏幕上完全可见。
我知道这是一个简单的问题,但我已经研究了几天,无法解决。
答案 0 :(得分:0)
好吧,原来我的前提有缺陷。
相机深度(在远平面Z = 1和近平面Z = 0之间测量)与世界Z值不是线性比例。
因此,我发现我需要首先使用projectPoint
从摄像机深度确定世界Z值。