// // ViewController.swift // ARR2D2 // // Created by Charlie Barber on 7/7/21. // import UIKit import Metal import MetalKit import ARKit extension MTKView : RenderDestinationProvider { } class ViewController: UIViewController, MTKViewDelegate, ARSessionDelegate { var session: ARSession! var renderer: Renderer! override func viewDidLoad() { super.viewDidLoad() // Set the view's delegate session = ARSession() session.delegate = self // Set the view to use the default device if let view = self.view as? MTKView { view.device = MTLCreateSystemDefaultDevice() view.backgroundColor = UIColor.clear view.delegate = self guard view.device != nil else { print("Metal is not supported on this device") return } // Configure the renderer to draw to the view renderer = Renderer(session: session, metalDevice: view.device!, renderDestination: view) renderer.drawRectResized(size: view.bounds.size) } let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTap(gestureRecognize:))) view.addGestureRecognizer(tapGesture) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Create a session configuration let configuration = ARWorldTrackingConfiguration() // configuration.planeDetection = [.horizontal] // Run the view's session session.run(configuration) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Pause the view's session session.pause() } @objc func handleTap(gestureRecognize: UITapGestureRecognizer) { // Create anchor using the camera's current position if let currentFrame = session.currentFrame { // Create a transform with a translation of 0.2 meters in front of the camera var translation = matrix_identity_float4x4 var scale = matrix_identity_float4x4 translation.columns.3.z = -2 scale.columns.0.x = 0.1 scale.columns.1.y = 0.1 scale.columns.2.z = 0.1 let rotationY = float4x4().rotateYAxis(by: 180) let rotationZ = float4x4().rotateZAxis(by: 270) let rotation = rotationY * rotationZ let tranformation = translation * scale * rotation let transform = simd_mul(currentFrame.camera.transform, tranformation) // Add a new anchor to the session let anchor = ARAnchor(transform: transform) session.add(anchor: anchor) } } // MARK: - MTKViewDelegate // Called whenever view changes orientation or layout is changed func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { renderer.drawRectResized(size: size) } // // Called whenever the view needs to render func draw(in view: MTKView) { renderer.update() } // MARK: - ARSessionDelegate func session(_ session: ARSession, didAdd anchors: [ARAnchor]) { for anchor in anchors { guard let planeAnchor = anchor as? ARPlaneAnchor else { return } if let currentFrame = session.currentFrame { // Create a transform with a translation of 0.2 meters in front of the camera var translation = matrix_identity_float4x4 var scale = matrix_identity_float4x4 translation.columns.3.x = -0.077392 translation.columns.3.y = -1.280197 translation.columns.3.z = -1.772298 scale.columns.0.x = 0.1 scale.columns.1.y = 0.1 scale.columns.2.z = 0.1 let rotationY = float4x4().rotateYAxis(by: 180) let rotationZ = float4x4().rotateZAxis(by: 270) let rotation = rotationY * rotationZ let tranformation = translation * scale * rotation let transform = simd_mul(currentFrame.camera.transform, tranformation) let anchoredObject = ARAnchor(transform: transform) session.add(anchor: anchoredObject) } } } func session(_ session: ARSession, didFailWithError error: Error) { // Present an error message to the user } func sessionWasInterrupted(_ session: ARSession) { // Inform the user that the session has been interrupted, for example, by presenting an overlay } func sessionInterruptionEnded(_ session: ARSession) { // Reset tracking and/or remove existing anchors if consistent tracking is required } }