iOS ARKit教程–增强现实iOS应用

时间:2020-02-23 14:45:53  来源:igfitidea点击:

在本教程中,我们将使用ARKit和SceneKit开发第一个增强现实iOS应用程序。

前提条件:

  • XCode 9或者以上

  • iPhone 6s或者更高版本,因为ArKit需要A9处理器。

  • iOS 11或者更高版本。

ARKit简介

  • Apple在WWDC 2016中引入了ARKit库。

  • 它允许开发人员构建增强现实应用程序。

  • 增强现实应用程序使我们可以通过摄像机在真实环境中查看虚拟对象。

  • 增强现实就像虚拟现实和现实世界的混合体。

  • 我们可以在ARKit场景中放置2D或者3D对象。
    对于2D对象,使用SpriteKit iOS库。
    对于3D对象,使用SceneKit。

接下来要构建的基本增强现实iOS应用将使用SceneKit。

3D模型的格式为DAE和SCN。

我们可以使用免费的Blender软件创建自定义3D模型。

现在就开始进行开发。

iOS ARKit入门

启动您的XCode并创建一个新项目。
确保已为本教程选择了模板作为"增强现实应用程序"。

在下一个屏幕上,确保已选择SceneKit。

现在,XCode创建您的第一个ARKit项目。

iOS ARKit教程项目结构

创建了一个" ship.scn" 3D示例模型。

3D模型离原点有些距离。
可以从右侧的属性面板更改此设置。

在MainStoryboard上,SceneView已链接到ViewController。

ViewController.swift有一个样板代码,用于设置scn文件并开始AR跟踪。

让我们在设备上运行此示例增强现实应用程序。

单击运行时,您可能会在XCode中获得以下对话框。

从设置信任应用程序之后,以下是应用程序的输出:

哇!屏幕上显示了船用3D模型。

但是起源其中?我们如何改变船舶的大小和位置?底部的统计数据如何显示?我们如何在场景上添加另一个3D对象?

我们将在下一节中讨论其中的每一个,同时还将介绍Swift代码。

下面给出了ViewController.swift的默认代码:

" ARSCNView"类是用于在AR SceneView中显示3D对象的视图。
ViewController类符合协议ARSCNViewDelegate。

sceneView.showsStatistics = true用于在屏幕底部显示统计信息,例如fps等。

sceneView.session返回一个ARSession。
在此基础上,我们通过在run方法中设置配置来运行AR跟踪。

修改模型的比例和位置

我们可以通过以下方式修改Model(在这种情况下为船)的比例尺和位置:

模型的位置是SCNNode相对于摄像机的位置。

正数x在右边。
负x在左边。

y为正。
负y下降。

正数z向后。
负z是正向。

更改比例以使模型显得更短

在上面的示例中,我们将scn模型设置为原点。

添加一个SCNBox

让我们在下面的ViewController.swift中添加一个SCNBox:

import UIKit
import SceneKit
import ARKit

class ViewController: UIViewController, ARSCNViewDelegate {

@IBOutlet var sceneView: ARSCNView!
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.showWorldOrigin
      
      //Create a new scene
      let scene = SCNScene(named: "art.scnassets/ship.scn")!
      
      //Set the scene to the view
      sceneView.scene = scene
      addBox()
  }
  
  override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(animated)
      
      //Create a session configuration
      let configuration = ARWorldTrackingConfiguration()

      //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()
  }
  
  override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      //Release any cached data, images, etc that aren't in use.
  }

  //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 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)
  }
}

sceneView.debugOptions = ARSCNDebugOptions.showWorldOrigin用于显示摄像机场景中的原点和坐标线。

在addBox()函数中,将形状框的SCNNode添加到ARSCNView中的场景中。

运行上述应用程序时的输出如下:

因此,我们的SCNBox设置在原点的前面,并显示为白色。

更改SCNBox的背景颜色

上面的SCNNode就像一个SCNBox,具有六个侧面。
让我们在每一侧设置不同的颜色。

将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)
      
      let colors = [UIColor.green, //front
          UIColor.red, //right
          UIColor.blue, //back
          UIColor.yellow, //left
          UIColor.purple, //top
          UIColor.gray] //bottom
      
      let sideMaterials = colors.map { color -> SCNMaterial in
          let material = SCNMaterial()
          material.diffuse.contents = color
          material.locksAmbientWithDiffuse = true
          return material
      }
      boxNode.geometry?.materials = sideMaterials
      sceneView.scene.rootNode.addChildNode(boxNode)
  }

我们使用盒子上的materials属性,并通过将它们映射到指定的SCNMaterial,从每一面的数组设置不同的UI颜色。