2017-08-25 56 views
0

我有一个SCNSphere,我想在屏幕像素(或更准确地说,点)中获得它的投影大小。如何以像素为单位计算SCNNode的大小?

我认为这将做到这一点:

let bounds = endNode.boundingBox 
let projectedMin = renderer.projectPoint(bounds.min) 
let projectedMax = renderer.projectPoint(bounds.max) 
let sizeInPts = CGSize(width: CGFloat(projectedMax.x - projectedMin.x), height: CGFloat(projectedMax.y - projectedMin.y)) 

但是不起作用。 sizeInPts的宽度和高度始终没有问题。

+0

...这很清楚为什么上述不起作用。从世界单位坐标到屏幕坐标时,用projectPoint投影_bounds_将被夸大。但仍然不确定正确的做法是什么。 –

回答

2

我想你应该检查边界框的所有顶点。
我没有测试这段代码,但我希望它能正常工作。

let (localMin, localMax) = endNode.boundingBox 
let min = endNode.convertPosition(localMin, to: nil) 
let max = endNode.convertPosition(localMax, to: nil) 
let arr = [ 
    renderer.projectPoint(SCNVector3(min.x, min.y, min.z)), 
    renderer.projectPoint(SCNVector3(max.x, min.y, min.z)), 
    renderer.projectPoint(SCNVector3(min.x, max.y, min.z)), 
    renderer.projectPoint(SCNVector3(max.x, max.y, min.z)), 
    renderer.projectPoint(SCNVector3(min.x, min.y, max.z)), 
    renderer.projectPoint(SCNVector3(max.x, min.y, max.z)), 
    renderer.projectPoint(SCNVector3(min.x, max.y, max.z)), 
    renderer.projectPoint(SCNVector3(max.x, max.y, max.z)) 
] 
let minX: CGFloat = arr.reduce(CGFloat.infinity, { $0 > $1.x ? $1.x : $0 }) 
let minY: CGFloat = arr.reduce(CGFloat.infinity, { $0 > $1.y ? $1.y : $0 }) 
let minZ: CGFloat = arr.reduce(CGFloat.infinity, { $0 > $1.z ? $1.z : $0 }) 
let maxX: CGFloat = arr.reduce(-CGFloat.infinity, { $0 < $1.x ? $1.x : $0 }) 
let maxY: CGFloat = arr.reduce(-CGFloat.infinity, { $0 < $1.y ? $1.y : $0 }) 
let maxZ: CGFloat = arr.reduce(-CGFloat.infinity, { $0 < $1.z ? $1.z : $0 }) 

let width = maxX - minX 
let height = maxY - minY 
let depth = maxZ - minZ 

let sizeInPts = CGSize(width: width, height: height) 

我将Xcode Playground示例上传到Github

+0

我认为这遭受同样的问题。想象一下,球体半径为1米,但距离相机1米远,所以在屏幕上它看起来高约30尺高。投影到屏幕坐标中的该球体的_center_将是准确的,但该球体的_bounding box_仍处于世界坐标中,所以当您将顶点投影到屏幕空间时,会得到非常夸张的东西,就好像相机距离节点0m。 –

+0

它取决于投影矩阵,但如果使用透视摄像机(renderer.pointOfView.camera.usesOrthographicProjection == false),则投影边界框应远离相机。 – magicien

+0

或者您可以从视图中选择不同的渲染器。您可以使用SCNView作为SCNSceneRenderer(view.projectPoint(...)) – magicien

相关问题