2017-08-25 4 views
0

J'ai un SCNSphere et j'aimerais obtenir sa taille projetée en pixels d'écran (ou plus précisément, des points).Comment calculer la taille de SCNNode en pixels?

Je pensais que ce serait le faire:

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)) 

Cependant, cela ne fonctionne pas. La largeur et la hauteur dans sizeInPts est toujours loin.

+0

... et il est assez clair pourquoi ce qui précède ne fonctionne pas. Projeter le _bounds_ avec projectPoint va être exagéré en passant des coords d'unité du monde à des coords d'écran. Mais je ne sais toujours pas quelle est la bonne façon de le faire. –

Répondre

2

Je pense que vous devriez vérifier tous les sommets de la boîte englobante.
Je n'ai pas testé ce code, mais j'espère que cela fonctionne.

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) 

J'ai téléchargé l'exemple Playground Xcode à Github.

+0

Je pense que cela souffre du même problème. Imaginez que la sphère est à un rayon de .1m mais qu'elle se trouve à 1m de la caméra, de sorte qu'elle semble avoir environ 30pts de hauteur et de largeur à l'écran. Le centre de cette sphère projeté dans les coordonnées de l'écran sera précis, mais la case de cette sphère est toujours dans les coordonnées du monde, donc quand vous projetez les sommets sur l'écran, vous obtenez quelque chose de très exagéré. –

+0

Cela dépend de la matrice de projection, mais si vous utilisez la caméra perspective (renderer.pointOfView.camera.usesOrthographicProjection == false), la zone de projection projetée doit être plus petite lorsqu'elle est éloignée de la caméra. – magicien

+0

Ou vous pouvez choisir le rendu différent de la vue. Vous pouvez simplement utiliser SCNView comme SCNSceneRenderer (view.projectPoint (...)) – magicien