在全新AR開發專欄的第一篇咱們經過一個簡單的project(在顯示環境放置一個cube)來了解ARKit的核心功能與API特性。經過這個過程,你將瞭解ARKit如何在真實的設備中工做,從而與建立的3D對象進行交互。node
1.本部分教程使用的是原生iOS開發,目前不涉及Unity,主要使用SceneKit。 swift
2.使用的軟件版本:Xcode 9。session
3.使用的開發語言版本:Swift 4app
4.本系列專欄但願經過簡潔的語言與圖片幫助你們更好的理解ARKit開發流程,幫助你們開發出炫酷的AR應用。ide
打開Xcode,點擊File > New > Project…,選擇Single View App,點擊Next建立項目,命名爲ARKitDemo。學習
設置SceneKit View測試
打開Main.storyboard,將ARKit SceneKit視圖拖放到視圖控制器上。ui
而後將ARKit SceneKit視圖約束填充整個視圖控制器。spa
鏈接IBOutletcode
在ViewController.swift文件的頂部添加一個import語句來導入ARKit:
import ARKit
而後按住control鍵並從ARKit SceneKit視圖拖拽到ViewController.swift文件。當提示時,命名IBOutlet sceneView。能夠刪除didReceiveMemoryWarning() 方法,目前咱們並不須要它。
配置ARSCNView Session
咱們的AR應用程序是經過攝像頭觀察世界和周圍的環境。因此接下來咱們須要設置Camera:
配置ARKit SceneKit View。在ViewController類中插入如下代碼:
override func viewWillAppear(\_ animated: Bool) { super.viewWillAppear(animated) let configuration = ARWorldTrackingConfiguration() sceneView.session.run(configuration) }
在viewWillAppear(_:)方法中,咱們初始化了一個名爲ARWorldTrackingConfiguration的AR配置。主要用於實現World Tracking功能。
The World Tracking配置跟蹤設備的方向和位置,它還能經過設備的Camera探測真實世界的表面。
設置sceneView’s AR session來運行咱們剛剛初始化的配置。AR session管理視圖內容的運動跟蹤和camera圖像處理。
如今在ViewController中添加另外一個方法:
override func viewWillDisappear(\_ animated: Bool) { super.viewWillDisappear(animated) sceneView.session.pause() }
在viewWillDisappear(_:)方法中主要處理:中止tracking和視圖內容的圖像。
Camera 受權
在咱們運行應用程序以前,咱們須要通知用戶咱們將使用他們設備的攝像頭實現加強現實功能。這是iOS 10發佈以來的一個要求。
打開Info.plist。右鍵單擊空白區域並選擇Add row。設置私隱相機使用說明鍵。值能夠設置爲Augmented Reality。以下圖所示:
接下來咱們提早測試下Camera是否能夠順利的調用出來。將測試手機鏈接到Mac上。在Xcode上構建並運行該項目。該應用程序應該會提示你容許攝像頭進入。以下圖所示:
插入如下代碼到你的ViewController類:
func addBox() { let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0) let boxNode = SCNNode() boxNode.geometry = box boxNode.position = SCNVector3(0, 0, -0.2) let scene = SCNScene() scene.rootNode.addChildNode(boxNode) sceneView.scene = scene }
override func viewDidLoad() { super.viewDidLoad() addBox() }
接下來Build,打開camera,出現白色的box,效果以下圖:
addBox()的方法也能夠這樣寫:
func addBox() { let box = SCNBox(width: 0.05, height: 0.05, length: 0.05, chamferRadius: 0) let boxNode = SCNNode() boxNode.geometry = box boxNode.position = SCNVector3(0, 0, -0.2) sceneView.scene.rootNode.addChildNode(boxNode) }
在ViewController.swift文件中插入如下方法:
@objc func didTap(withGestureRecognizer recognizer: UIGestureRecognizer) { let tapLocation = recognizer.location(in: sceneView) let hitTestResults = sceneView.hitTest(tapLocation) guard let node = hitTestResults.first?.node else { return } node.removeFromParentNode() }
建立了一個didTap(帶有gesturerecognizer:)方法。檢索用戶相對於sceneView的點擊位置,而後t查看是否點擊了任何node。而後從hitTestResults中找到第一個node。若是結果確實包含至少一個node,那麼咱們將從其父節點刪除第一個節點。
在測試刪除對象以前,更新viewDidLoad()方法,添加對addTapGestureToSceneView()方法的調用:
override func viewDidLoad() { super.viewDidLoad() addBox() addTapGestureToSceneView() }
在ViewController類的末尾建立一個extension:
extension float4x4 { var translation: float3 { let translation = self.columns.3 return float3(translation.x, translation.y, translation.z) } }
extension將矩陣轉換爲float3。修改addBox()方法:
func addBox(x: Float = 0, y: Float = 0, z: Float = -0.2) { let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0) let boxNode = SCNNode() boxNode.geometry = box boxNode.position = SCNVector3(x, y, z) sceneView.scene.rootNode.addChildNode(boxNode) }
修改didTap(使用gesturerecognizer:)方法,在guard let語句內部和return語句以前。添加如下代碼:
let hitTestResultsWithFeaturePoints = sceneView.hitTest(tapLocation, types: .featurePoint) if let hitTestResultWithFeaturePoints = hitTestResultsWithFeaturePoints.first { let translation = hitTestResultWithFeaturePoints.worldTransform.translation addBox(x: translation.x, y: translation.y, z: translation.z) }
接下來實現使用x、y和z在檢測到的點擊時添加一個新的box。didTap(withGestureRecognizer:)方法的代碼以下:
@objc func didTap(withGestureRecognizer recognizer: UIGestureRecognizer) { let tapLocation = recognizer.location(in: sceneView) let hitTestResults = sceneView.hitTest(tapLocation) guard let node = hitTestResults.first?.node else { let hitTestResultsWithFeaturePoints = sceneView.hitTest(tapLocation, types: .featurePoint) if let hitTestResultWithFeaturePoints = hitTestResultsWithFeaturePoints.first { let translation = hitTestResultWithFeaturePoints.worldTransform.translation addBox(x: translation.x, y: translation.y, z: translation.z) } return } node.removeFromParentNode() }
運行效果以下圖:
關注公衆號: AIRX社區(國內領先的AI、AR、VR技術學習與交流平臺)
![]()