/
ViewController.swift
121 lines (90 loc) · 3.83 KB
/
ViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// ViewController.swift
// NextReality_Tutorial9
//
// Created by Ambuj Punn on 10/30/18.
// Copyright © 2018 Ambuj Punn. All rights reserved.
//
import UIKit
import SceneKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
var grids = [Grid]()
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
sceneView.debugOptions = ARSCNDebugOptions.showFeaturePoints
// Create a new scene
let scene = SCNScene()
// Set the scene to the view
sceneView.scene = scene
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
sceneView.addGestureRecognizer(gestureRecognizer)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = .horizontal
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
// MARK: - ARSCNViewDelegate
/*
// Override to create and configure nodes for anchors added to the view's session.
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let node = SCNNode()
return node
}
*/
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
}
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let grid = Grid(anchor: planeAnchor)
self.grids.append(grid)
node.addChildNode(grid)
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let grid = self.grids.filter { grid in
return grid.anchor.identifier == planeAnchor.identifier
}.first
guard let foundGrid = grid else {
return
}
foundGrid.update(anchor: planeAnchor)
}
@objc func tapped(gesture: UITapGestureRecognizer) {
// Get 2D position of touch event on screen
let touchPosition = gesture.location(in: sceneView)
// Translate those 2D points to 3D points using hitTest (existing plane)
let hitTestResults = sceneView.hitTest(touchPosition, types: .existingPlaneUsingExtent)
guard let hitTest = hitTestResults.first else {
return
}
addTV(hitTest)
}
func addTV(_ hitTestResult: ARHitTestResult) {
let scene = SCNScene(named: "art.scnassets/tv.scn")!
let tvNode = scene.rootNode.childNode(withName: "tv_node", recursively: true)
tvNode?.position = SCNVector3(hitTestResult.worldTransform.columns.3.x,hitTestResult.worldTransform.columns.3.y, hitTestResult.worldTransform.columns.3.z)
self.sceneView.scene.rootNode.addChildNode(tvNode!)
}
}