如何获取SceneKit SCNCameraController frameNodes来设置目标

时间:2018-01-06 01:01:49

标签: ios scenekit

iOS 11中的新SCNCameraController看起来非常有用,但不幸的是,除了头文件和WWDC2017视频中的简短描述之外,似乎没有任何其他文档。 frameNodes 功能看起来特别方便,但它似乎并不实际工作或至少不可靠。具体来说,frameNodes的标题注释说:

“将相机移动到所有节点的边界球体完全可见的位置。同时设置相机目标具有边界球体的中心。”

对于具有多个条目的节点数组,它通常会调整相机以使它们全部可见,但几乎从未将相机控制器目标设置为节点的边界球。至少我无法让它可靠地工作。有没有人想出如何让它工作(我使用的是iOS 11.2.1和Xcode 9.2)?

我附上了一个游乐场来演示这个问题。如果我没有手动设置cameraController.target,则摄像机围绕圆环旋转,即目标似乎设置为SCNVector(0,0,0)。如果我手动设置目标,那么相机似乎围绕正确的目标旋转,大致在圆环和立方体之间。如果这只是我可以解决的错误,那么有人可以建议(简单明了吗?)计算节点数组的边界体积吗?

import UIKit
import SceneKit
import PlaygroundSupport

var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
var scene = SCNScene()
sceneView.scene = scene
PlaygroundPage.current.liveView = sceneView

sceneView.autoenablesDefaultLighting = true

var cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
scene.rootNode.addChildNode(cameraNode)

sceneView.allowsCameraControl = true
sceneView.defaultCameraController.interactionMode = .orbitTurntable
sceneView.defaultCameraController.pointOfView = sceneView.pointOfView

var torus = SCNTorus(ringRadius: 1, pipeRadius: 0.5)
var torusNode = SCNNode(geometry: torus)
torusNode.position = SCNVector3(0, 0, 0)
scene.rootNode.addChildNode(torusNode)
torus.firstMaterial?.diffuse.contents  = UIColor.red
torus.firstMaterial?.specular.contents = UIColor.white

var cube = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
var cubeNode = SCNNode(geometry: cube)
cubeNode.position = SCNVector3(4, 0, 0)
scene.rootNode.addChildNode(cubeNode)
cube.firstMaterial?.diffuse.contents  = UIColor.blue
cube.firstMaterial?.specular.contents = UIColor.white

SCNTransaction.begin()
SCNTransaction.animationDuration = 1.0
sceneView.defaultCameraController.frameNodes([torusNode, cubeNode])
//sceneView.defaultCameraController.target = SCNVector3(2, 0, 0)
SCNTransaction.commit()

1 个答案:

答案 0 :(得分:0)

通过创建半径等于x,y,z数组中最大x,y或z值(float)的球体,可以显示节点数组的边界体积。

下面的伪代码:

maxval = 0
for i in x[] {
  if i > maxval {
     maxval = i
  }
}
for i in y[] {
  if i > maxval {
     maxval = i
  }
}
for i in z[] {
  if i > maxval {
     maxval = i
  }
}
let a = SCNSPhere(radius: maxval)