Last active
December 1, 2019 06:04
-
-
Save digitallysavvy/d78783f8d886d20d26356d70c386cb1b to your computer and use it in GitHub Desktop.
A simple ARSCN View Controller with full render delegate list.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ARViewController.swift | |
// | |
// Created by digitallysavvy. | |
// Copyright © 2019 digitallysavvy All rights reserved. | |
// | |
import UIKit | |
import ARKit | |
internal class ARViewController: UIViewController, ARSCNViewDelegate, ARSessionDelegate { | |
var sceneView : ARSCNView! | |
var scnLights : [SCNNode] = [] | |
let debug : Bool = true // toggle the debug logs | |
// MARK: VC Events | |
override func loadView() { | |
super.loadView() | |
self.view.backgroundColor = UIColor.black // set the background color | |
// Setup sceneview | |
let sceneView = ARSCNView() //instantiate scene view | |
self.view.insertSubview(sceneView, at: 0) | |
//add sceneView layout contstraints | |
sceneView.translatesAutoresizingMaskIntoConstraints = false | |
sceneView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true | |
sceneView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true | |
sceneView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true | |
sceneView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true | |
// set reference to sceneView | |
self.sceneView = sceneView | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// set ARKit render and session delegates | |
self.sceneView.delegate = self | |
self.sceneView.session.delegate = self | |
if debug { | |
self.sceneView.debugOptions = [ARSCNDebugOptions.showWorldOrigin, ARSCNDebugOptions.showFeaturePoints, .showBoundingBoxes] | |
self.sceneView.showsStatistics = true | |
} | |
} | |
override func viewWillAppear(_ animated: Bool) { | |
super.viewWillAppear(animated) | |
// Configure ARKit Session | |
let configuration = ARWorldTrackingConfiguration() // ARKit trackign configuration | |
configuration.planeDetection = [.horizontal, .vertical] | |
configuration.providesAudioData = true // enable audio data | |
configuration.isLightEstimationEnabled = true // enable light estimation (save on processing) | |
self.sceneView.session.run(configuration) // set cunfiguration for ARKit session | |
} | |
override func viewDidAppear(_ animated: Bool) { | |
super.viewDidAppear(animated) | |
let light = self.createLight(withPosition: SCNVector3(x: 0,y: 5,z: 0), andEulerRotation: SCNVector3(-Float.pi / 2, 0, 0)) | |
self.sceneView.scene.rootNode.addChildNode(light) | |
self.scnLights.append(light) | |
} | |
override func viewWillDisappear(_ animated: Bool) { | |
super.viewWillDisappear(animated) | |
// Pause the view's session | |
self.sceneView.session.pause() | |
self.sceneView.removeFromSuperview() | |
self.sceneView = nil | |
} | |
// MARK: Hide status bar | |
override var prefersStatusBarHidden: Bool { | |
return true | |
} | |
// MARK: Render delegate | |
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) { | |
guard let currentFrame = self.sceneView.session.currentFrame else { return } | |
let intensity : CGFloat = currentFrame.lightEstimate!.ambientIntensity / 1000.0 | |
self.sceneView.scene.lightingEnvironment.intensity = intensity | |
if scnLights.count > 0 { | |
for node in scnLights { | |
node.light?.intensity = intensity | |
} | |
} | |
// do something when scene will render | |
} | |
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { | |
// do something on render update | |
} | |
func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) { | |
} | |
// plane detection | |
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { | |
// anchor plane detection | |
} | |
// plane updating | |
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { | |
// anchor plane is updated | |
} | |
func renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) { | |
// anchor plane is removed | |
} | |
// MARK: Session delegate | |
func session(_ session: ARSession, didUpdate frame: ARFrame) { | |
// ARSession did update | |
} | |
func session(_ session: ARSession, didOutputAudioSampleBuffer audioSampleBuffer: CMSampleBuffer) { | |
// ARSession did output audio data | |
} | |
func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) { | |
// ARSession camera tracking state change | |
} | |
func sessionWasInterrupted(_ session: ARSession) { | |
// ARSession was interrupted | |
} | |
func sessionInterruptionEnded(_ session: ARSession) { | |
// ARSession interuption ended | |
} | |
func sessionShouldAttemptRelocalization(_ session: ARSession) -> Bool { | |
// whether to attempt recovery of world-tracking state after an interruption. | |
return true | |
} | |
// MARK: Lights | |
func createLight(withPosition position: SCNVector3, andEulerRotation rotation: SCNVector3) -> SCNNode { | |
// Create a directional light node with shadow | |
let directionalNode : SCNNode = SCNNode() | |
directionalNode.light = SCNLight() | |
directionalNode.light?.type = SCNLight.LightType.directional | |
directionalNode.light?.color = UIColor.white | |
directionalNode.light?.castsShadow = true | |
directionalNode.light?.automaticallyAdjustsShadowProjection = true | |
directionalNode.light?.shadowSampleCount = 64 | |
directionalNode.light?.shadowRadius = 16 | |
directionalNode.light?.shadowMode = .deferred | |
directionalNode.light?.shadowMapSize = CGSize(width: 1024, height: 1024) | |
directionalNode.light?.shadowColor = UIColor.black.withAlphaComponent(0.5) | |
directionalNode.position = position | |
directionalNode.eulerAngles = rotation | |
return directionalNode | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment