Improvements to resizing/reorientation

This commit is contained in:
Charles Magahern
2019-10-13 15:40:13 -07:00
parent 1dca4b98e5
commit 6a8eec5a07
3 changed files with 102 additions and 31 deletions
@@ -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