Improvements to resizing/reorientation
This commit is contained in:
@@ -15,20 +15,24 @@ import SceneKit
|
||||
|
||||
let π = CGFloat(Double.pi)
|
||||
|
||||
class VisualizationViewController: UIViewController
|
||||
class VisualizationViewController: UIViewController, SCNSceneRendererDelegate
|
||||
{
|
||||
fileprivate var _scene: SCNScene = SCNScene()
|
||||
fileprivate var _sceneView: SCNView?
|
||||
fileprivate var _cameraNode: SCNNode = SCNNode()
|
||||
fileprivate var _lightNode: SCNNode = SCNNode()
|
||||
fileprivate var _cubletsNode: SCNNode = SCNNode()
|
||||
fileprivate var _cublets: [SCNNode] = []
|
||||
fileprivate var _percentActivated: Float = 0.0
|
||||
fileprivate let _scene: SCNScene = SCNScene()
|
||||
fileprivate let _cameraNode: SCNNode = SCNNode()
|
||||
fileprivate let _lightNode: SCNNode = SCNNode()
|
||||
fileprivate var _cubletsNode: SCNNode = SCNNode()
|
||||
fileprivate var _sceneView: SCNView?
|
||||
fileprivate var _cublets: [SCNNode] = []
|
||||
fileprivate var _percentActivated: Float = 0.0
|
||||
|
||||
fileprivate let _rendererDataQueue: DispatchQueue = DispatchQueue(label: "RendererQueue")
|
||||
fileprivate var _rendererViewBounds: CGRect = .zero
|
||||
|
||||
static fileprivate let cubletsDimensions = 5
|
||||
static fileprivate let cubletsSize = 1.0
|
||||
static fileprivate let cubletsSpacing = 2.0
|
||||
static fileprivate let rotationAnimationKey = "RotationAnimation"
|
||||
static fileprivate let cameraAdditionalDistance = Float(8.0)
|
||||
|
||||
// MARK: Overrides
|
||||
|
||||
@@ -39,6 +43,7 @@ class VisualizationViewController: UIViewController
|
||||
view.backgroundColor = UIColor.black
|
||||
view.scene = _scene
|
||||
view.allowsCameraControl = false
|
||||
view.delegate = self
|
||||
|
||||
_sceneView = view
|
||||
self.view = view
|
||||
@@ -68,6 +73,16 @@ class VisualizationViewController: UIViewController
|
||||
_sceneView?.stop(nil)
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews()
|
||||
{
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
let bounds = self.view.bounds
|
||||
_rendererDataQueue.async {
|
||||
self._rendererViewBounds = bounds
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: API
|
||||
|
||||
var connectionStatus: ConnectionStatus = .disconnected
|
||||
@@ -146,6 +161,13 @@ class VisualizationViewController: UIViewController
|
||||
_percentActivated = percentage
|
||||
}
|
||||
|
||||
// MARK: SCNSceneRendererDelegate
|
||||
|
||||
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
|
||||
{
|
||||
_recomputeCameraDistance()
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
internal func _setupCamera()
|
||||
@@ -153,7 +175,6 @@ class VisualizationViewController: UIViewController
|
||||
let camera = SCNCamera()
|
||||
|
||||
_cameraNode.camera = camera
|
||||
_cameraNode.position = SCNVector3Make(0.0, 0.0, 30.0)
|
||||
_scene.rootNode.addChildNode(_cameraNode)
|
||||
|
||||
let centerNode = SCNNode()
|
||||
@@ -169,12 +190,9 @@ class VisualizationViewController: UIViewController
|
||||
let light = SCNLight()
|
||||
light.type = SCNLight.LightType.omni
|
||||
light.color = UIColor.white
|
||||
|
||||
_lightNode = SCNNode()
|
||||
_lightNode.light = light
|
||||
_lightNode.position = _cameraNode.position
|
||||
|
||||
_scene.rootNode.addChildNode(_lightNode)
|
||||
_cameraNode.addChildNode(_lightNode)
|
||||
}
|
||||
|
||||
internal func _setupModel()
|
||||
@@ -240,6 +258,36 @@ class VisualizationViewController: UIViewController
|
||||
_sceneView?.technique = technique
|
||||
}
|
||||
|
||||
internal func _recomputeCameraDistance()
|
||||
{
|
||||
// compute how far the camera must be from the origin in order to fit the
|
||||
// entire scene into the current viewport size.
|
||||
|
||||
guard let renderer = _sceneView else { return }
|
||||
guard let camera = _cameraNode.camera else { return }
|
||||
|
||||
let viewBounds = _rendererDataQueue.sync { _rendererViewBounds }
|
||||
let worldMin = renderer.unprojectPoint(SCNVector3(
|
||||
viewBounds.origin.x,
|
||||
viewBounds.origin.y,
|
||||
0.0
|
||||
))
|
||||
let worldMax = renderer.unprojectPoint(SCNVector3(
|
||||
viewBounds.origin.x + viewBounds.size.width,
|
||||
viewBounds.origin.y + viewBounds.size.height,
|
||||
0.0
|
||||
))
|
||||
let farX = worldMax.x - worldMin.x
|
||||
|
||||
let fov = Float(camera.fieldOfView)
|
||||
let aabb = _cubletsNode.boundingBox
|
||||
let minO = (aabb.max.x - aabb.min.x) / farX
|
||||
let halfMinO = minO / 2.0
|
||||
let cameraDistance = (halfMinO / tan(fov)) + Self.cameraAdditionalDistance
|
||||
|
||||
_cameraNode.position = SCNVector3Make(0.0, 0.0, cameraDistance)
|
||||
}
|
||||
|
||||
internal func _beginModelResetTimer()
|
||||
{
|
||||
/* since this visualization is running all the time, trigonometric functions begin
|
||||
|
||||
Reference in New Issue
Block a user