ARKit的学习

概述

ARKit.png

iOS 11 引入了 ARKit,这是一个全新的框架,允许开发者轻松地为 iPhone 和 iPad 创建无与伦比的增强现实体验。通过将虚拟对象和虚拟信息同用户周围的环境相互融合,ARKit 使得应用跳出屏幕的限制,让它们能够以全新的方式与现实世界进行交互。

视觉惯性测距【全局追踪】

ARKit 使用视觉惯性测距 (Visual Inertial Odometry, VIO) 来精准追踪周围的世界。VIO 将摄像头的传感器数据同 Core Motion 数据进行融合。这两种数据允许设备能够高精度地感测设备在房间内的动作,而且无需额外校准。

场景识别与光亮估量【场景理解】

借助 ARKit,iPhone 和 iPad 可以分析相机界面中所呈现的场景,并在房间当中寻找水平面。ARKit 不仅可以检测诸如桌子和地板之类的水平面,还可以在较小特征点 (feature points) 上追踪和放置对象。ARKit 还利用摄像头传感器来估算场景当中的可见光总亮度,并为虚拟对象添加符合环境照明量的光量。

高性能硬件与渲染优化【渲染】

ARKit 运行在 Apple A9 和 A10 处理器上。这些处理器能够为 ARKit 提供突破性的性能,从而可以实现快速场景识别,并且还可以让您基于现实世界场景,来构建详细并引人注目的虚拟内容。您可以利用 MetalScenekitSpritekit 以及诸如UnityUNREAL ENGINE之类的第三方工具,来对 ARKit 进行优化。


ARKit与SceneKit

  • ARKit:相机捕捉真实世界
  • Scenekit:制作3D模型
<ARKit>与<SceneKit>框架关系图.jpg
  • 大家可以看到图中的 ARSession 类,配置 ARSession,然后使用 SceneKit 或者 SpriteKit 来展示 AR 内容。ARSCNViewARSKView 类都是包含在 ARSession 当中的,而 ARSession 对象则用来管理设备动作追踪和进行图像处理的,也就是创建 AR 场景的必需品。但是,要运行 Session,您首先必须选择一种 Session 配置。

    • ARWorldTrackingConfiguration:提供高品质的AR体验,可精确跟踪设备的位置和方向,并允许平面检测和命中测试。
      f76d63a3-7620-40d1-9e52-0d9ad6329678.png
    • AROrientationTrackingConfiguration:提供仅跟踪设备方向的基本AR体验。
      ba51d1f9-896b-4b97-a87a-a3db9032eb00.png

      然后,我们在这个配置上调用run()函数。该会话还具有同时运行的AVCaptureSession和CMMotionManager对象,以获取用于跟踪的图像和运动数据。最后,会话将当前帧输出到ARFrame对象。
  • SCNScene:节点【万物皆Scene】,每一个Scene都有个根节点RootNode。如图所示节点类似于NSObject,节点就可以看做是3D物件。


跟踪设备方向的基本配置

ARFrame:捕获和位置追踪、视频图像信息。
ARFrame
ARAnchor:一个真实的位置和方向,可用于将对象放置在一个基于“增大化现实”技术的游戏场景。
ARAnchor
Tracking:如图x、y、z三个轴组成,z轴负数的情况下说明显示在相机前面的位置,正数的时候显示在相机后面的位置。
Tracking

AR应用程序

app结构.png

如图:

  • ARKit负责采集场景;
  • SceneKit、SpriteKit、Metal负责渲染;
    • SpriteKit:在很久以前做平面、立体大家都要依靠OpenCV、OpenGL,由于比较难用,后来有人封装成cocos2d。苹果后来在cocos2d基础上又封装一层,也就是现在的SpriteKit。效果不错后iOS8又推出了SceneKit;
    • Metal:用来操作GPU;【GPU处理事情的时候是同步处理】

开发环境和适配设备

  • Xcode:Xcode9以上版本,最新已更新到到 【Xcode9-beta 6】。
  • 设备:需要具有A9或更高版本处理器的iOS设备。
  • 系统:当然是iOS11喽,最新已更新到 【iOS 11 beta 9】,然后下载描述文件。安装描述文件,重新启动。检查软件更新就可以了。

项目创建

项目创建

选择SceneKit3D模型

选择SceneKit

工程创建后初始代码

   override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        // SCNScene:场景里面包含一个模型,然后把场景放到ARSCNView上,然后就可以展示。
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        
        // Set the scene to the view
        sceneView.scene = scene
   }

   override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // Create a session configuration
        let configuration = ARWorldTrackingConfiguration()

        // 通过`run()`启动追踪
        sceneView.session.run(configuration)
        
    }
    
   override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        //通过`pause()`暂停
        sceneView.session.pause()
    }

真机直接运行

真机运行第一次会提示相机权限,开启后显示出一个3D飞机在相机前。

运行.gif

下面我们创建一张相机截图显示在手机屏幕前

通过添加手势,点击后生成截屏图片显示在手机前。

 @objc func handtap(gestureRecognizer:UITapGestureRecognizer){
        
        guard let currentFrame = sceneView.session.currentFrame else {
            return
        }
        /// 创建图片
        let imagePlane = SCNPlane(width: sceneView.bounds.width / 6000, height: sceneView.bounds.height / 6000)
        /// 渲染图片
        imagePlane.firstMaterial?.diffuse.contents = sceneView.snapshot() //截屏
        imagePlane.firstMaterial?.lightingModel = .constant
        /// 创建节点并添加到sceneView上
        let planNode = SCNNode(geometry: imagePlane)
        sceneView.scene.rootNode.addChildNode(planNode)
        /// 追踪相机位置
        var translate = matrix_identity_float4x4
        translate.columns.3.z = -0.1
        ///取相机里面的数据,放到simdTransform
        planNode.simdTransform = matrix_multiply(currentFrame.camera.transform, translate)
    }

firstMaterial:渲染
sceneView.snapshot():sceneView全部内容展示出来【截屏】
matrix_identity_float4x4:【4x4矩阵,x、y、z、高度的部分】
translate.columns.3.z = -0.1:追踪的位置是在3轴的z轴-0.1的位置

运行结果

下面我们不用程序默认的模型,我们来创建自己的模型,直接代码走起

1. 创建一个盒子模型,并进行渲染。

        let scene = SCNScene()
        /// 我们创建几何模型:盒子
        /// chamferRadius:圆角,等于0时,说明是没有圆角
        let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
        /// 创建节点,传入几何
        let boxNode = SCNNode(geometry: box)
        /// 对盒子进行渲染
        /// 创建渲染器
        /// material 渲染器
        let material = SCNMaterial()
        /// 渲染成红色
        //material.diffuse.contents = UIColor.red
        /// 渲染一张照片
        material.diffuse.contents = UIImage(named: "brick.png")
        /// 渲染盒子
        box.materials = [material]
        /// 设置节点位置
        /// SCNVector3:三维【x,y.z]
        boxNode.position = SCNVector3(0,0,-0.2)
        /// 把结点放到根节点上
        scene.rootNode.addChildNode(boxNode)

        sceneView.scene = scene

运行效果


2. 创建球体模型,再点击球体后,进行不同图片的渲染。

@IBOutlet var sceneView: ARSCNView!
    
    let textures = ["earth.jpg","jupiter.jpg","mars.jpg","venus.jpg","IMG_0008.jpg"]
    private var index = 1
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Set the view's delegate
        sceneView.delegate = self
        
        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        
        let scene = SCNScene()
        /// 我们创建几何模型:球体
        let sphere = SCNSphere(radius: 0.1)
        /// 渲染
        let material = SCNMaterial()
        material.diffuse.contents = UIImage(named: "earth.jpg")
        sphere.materials = [material]
        /// 创建节点
        let sphereNode = SCNNode(geometry: sphere)
        sphereNode.position = SCNVector3(0,0,-0.5)
        scene.rootNode.addChildNode(sphereNode)
        
        sceneView.scene = scene
         /// 创建手势
        registerGestureRecognizers()
    }
    
    func registerGestureRecognizers(){
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapped))
        self.sceneView.addGestureRecognizer(tapGestureRecognizer)
    }
    
    @objc func tapped (recognizer: UIGestureRecognizer){
        /// 获取ARSCNView
        let sceneView = recognizer.view as! ARSCNView
       /// 手势点击的位置
        let touchLoaction = recognizer.location(in: sceneView)
       /// 获取点击之后的结果
        let hitRersults = sceneView.hitTest(touchLoaction, options: [:])

        if  !hitRersults.isEmpty {
            if index == self.textures.count {
                index = 0
            }
            guard let hitRersult = hitRersults.first else {
                return
            }
          /// 更改渲染的图片
            let node = hitRersult.node
            node.geometry?.firstMaterial?.diffuse.contents = UIImage(named: textures[index])
            
            index += 1
        }
    }

运行效果


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • Introducing ARKit iOS 11 引入 ARKit,这是 个全新的框架,允许开发者轻松地为 iP...
    没八阿哥的程序阅读 2,407评论 1 9
  • ARkit Introducing ARKit iOS 11引入ARKit,这是 个全新的框架,允许开发者轻松地为...
    坤哥爱卿阅读 1,330评论 0 1
  • ARKit ARKit框架通过集成iOS设备摄像头和运动功能,在您的应用程序或游戏中产生增强现实体验。 概述 增强...
    暗夜夜夜行路阅读 5,792评论 0 17
  • 从小喜爱绘画,之前家里有多余的彩色铅笔,本着不浪费的原则开始了手绘彩铅,顺手书店活动价买了本手绘书,不过也就是过程...
    鲤迷心窍阅读 1,001评论 1 1
  • ——读《追风筝的人》有感 我其实很反感读国外的小说,那拗口的名字和不一样的文化背景,很难让人有入境感。不过,《偷影...
    爱君如初阅读 288评论 0 0