笔者在上篇文章中对ARKit进行了简单介绍,在本篇文章中主要介绍ARKit中经常用到的API及使用方法。了解这些API的含义以方便我们后边的深入学习。
1.1-ARAnchor
用于在AR场景中放置物体的一个现实世界的位置和方向,通常我们无需构造,因为添加一个3D物体时ARKit会有代理告知我们物体的ARAnchor实例。
ARAnchor拥有属性:transform,类型为matrix_float4x4(是一个4x4的矩阵),
构造方法:-(instancetype)initWithTransform:(matrix_float4x4)transform;
1.2-ARPlaneAnchor
继承自ARAnchor,是在ARSession中监测到的现实平面的位置和方向。
1.3-ARSession
一个管理增强现实所需的设备摄像头和动作处理的共享的对象。
ARSession对象会协调增强现实过程中的大部分处理,这些处理包括:从设备的动作感应硬件读取数据、控制设备内置摄像头和对捕捉到的摄像图像进行分析。ARSession会整合这些结果并在设备反馈的现实空间和模型化AR内容的虚拟空间之间建立一种对应关系。
任何一个用ARKit实现的AR场景都需要一个单独的ARSession对象。如果使用了ARSCNView或者ARSKView对象来创建了AR场景的话,一个ARSession实例已经包含在这个View之中了。如果通过别的渲染器来建立AR内容,就需要手动创建并维持一个ARSession对象。
运行一个session需要一个session configuration,这是一个ARSessionConfiguration或其子类ARWorldTrackingSessionConfiguration的实例。这些类决定了ARKit如何追踪一个设备的位置以及相对于现实世界的运动,因此影响了所创建的AR体验。
1.你对象提供接收视频图像捕获和跟踪信息,或对会话状态的变化,代理是捕获视频流的(方法可以实现接收视频帧图像捕获和跟踪状态的AR会话) var
self.arsession.delegate = self;
2.暂停 func
[self.arsession pause];
3.支持多线程的 var
self.arsession.delegateQueue ;
4.翻译为当前帧 var
ARFrame*frame = self.arsession.currentFrame;*
5.运行追踪者 func
[self.arsession runWithConfiguration:self.arsessionconfiguration];
6.增加删除锚点,func
ARAnchorar = [[ARAnchor alloc]initWithTransform:matrix_sub];
[self.arsession addAnchor:ar ];
[self.arsession removeAnchor:ar];
1.4-ARFrame
表示追踪相机当前的状态,这个状态不仅仅只是位置,还有图像帧及时间等参数,一个运行的ARSession会不断的通过设备相机捕捉视频帧。对于每一个frame,ARKit会结合图像和从设备运动感应硬件获得的数据来分析设备的真实位置。这些追踪信息和视图参数就是以ARFrame对象来保存和传递的。
@interfaceARFrame:NSObject/**
时间戳.
*/@property(nonatomic,readonly)NSTimeIntervaltimestamp;/**
缓冲区图像帧
*/@property(nonatomic,readonly) CVPixelBufferRef capturedImage;/**
相机(表示这个ARFrame是哪一个相机的,iPhone7plus有两个摄像机)
*/@property(nonatomic,copy,readonly) ARCamera *camera;/**
返回当前相机捕捉到的锚点数据(当一个3D虚拟模型加入到ARKit中时,锚点值得就是这个模型在AR中的位置)
*/@property(nonatomic,copy,readonly)NSArray *anchors;/**
灯光,详情可见本章节ARLightEstimate类介绍(指的是灯光强度 一般是0-2000,系统默认1000)
*/@property(nonatomic,copy,nullable,readonly) ARLightEstimate *lightEstimate;/**
特征点(应该是捕捉平地或者人脸的,比较苹果有自带的人脸识别功能)
*/@property(nonatomic,nullable,readonly) ARPointCloud *rawFeaturePoints;/**
根据2D坐标点搜索3D模型,这个方法通常用于,当我们在手机屏幕点击某一个点的时候,可以捕捉到这一个点所在的3D模型的位置,至于为什么是一个数组非常好理解。手机屏幕一个是长方形,这是一个二维空间。而相机捕捉到的是一个由这个二维空间射出去的长方体,我们点击屏幕一个点可以理解为在这个长方体的边缘射出一条线,这一条线上可能会有多个3D物体模型
point:2D坐标点(手机屏幕某一点)
ARHitTestResultType:捕捉类型 点还是面
(NSArray *):追踪结果数组 详情见本章节ARHitTestResult类介绍
*/- (NSArray *)hitTest:(CGPoint)point types:(ARHitTestResultType)types;/**
相机窗口的的坐标变换(可用于相机横竖屏的旋转适配)
*/- (CGAffineTransform)displayTransformWithViewportSize:(CGSize)viewportSize orientation:(UIInterfaceOrientation)orientation;
@end
1.5-ARCamera
表示AR session中一个被捕获的视图帧相关的相机位置和视图特征的信息。
****一般我们无需去创建一个相机,因为当我们初始化一个AR试图时,他会为我们默认创建一个相机,而且这个相机就是摄像头的位置,同时也是3D世界中的原点所在(x=0,y=0,z=0)
1.6-ARSessionConfiguration
一个仅用来追踪设备方向的基础设置,*主要就是追踪相机的配置。*****
所有的AR configuration都是用来建立现实世界和虚拟3D坐标空间的对应关系的。当app将这些虚拟内容和实时的摄像画面一起展示给用户,用户会产生一种这些虚拟内容是现实世界的一部分的错觉。
创建和维持各空间之间的对应关系需要追踪设备的移动。ARSessionConfiguration类用三自由度(3DOF,也就是三个旋转坐标:roll(绕x轴)、pitch(绕y轴)和yaw(绕z轴))。
这种最基础级别的运动追踪可以创建最基本的AR体验:一个虚拟物体可以出现在部分现实世界中,即使用户旋转设备从上、下或者侧面来观察这个物体。但是,无法追踪非平凡(non-trivially)的位置的变化,从而导致AR幻觉破碎,虚拟物体会相对于现实世界漂移。如用户无法看到虚拟物体的背面和其它部分。
ARSessionConfiguration类创建了有限的但是可用于所有iOS设备的AR体验,而增强的AR体验只在某些设备上可用。
//会话追踪配置类@interfaceARSessionConfiguration: NSObject /**
当前设备是否支持,一般A9芯片以下设备不支持
*/@property(class, nonatomic, readonly) BOOL isSupported;/**
会话的对其方式,这里的对其指的是3D世界的坐标。枚举值见下方
*/@property(nonatomic, readwrite) ARWorldAlignment worldAlignment;/**
是否需要自适应灯光效果,默认是YES
*/@property(nonatomic, readwrite, getter=isLightEstimationEnabled) BOOL lightEstimationEnabled;@end//世界会话追踪配置,苹果建议我们使用这个类,这个子类只有一个属性,也就是可以帮助我们追踪相机捕捉到的平地
@interfaceARWorldTrackingSessionConfiguration: ARSessionConfiguration/**
侦查类型。枚举值见下方(默认侦查平地)
*/@property(nonatomic, readwrite) ARPlaneDetection planeDetection;
@end
1.7-ARWorldTrackingSessionConfiguration
一个用于追踪设备方向和位置,并且监测现实世界平面的设置,它是ARSessionConfiguration的子类,并处于同一个API文件中。
相比于ARSessionConfiguration,ARWorldTrackingSessionConfiguration可以从六自由度来追踪设备的运动,除了上述三自由度,还包括三个平移坐标(表示在x、y、z轴上的移动)。
这种级别的追踪可以创建一个沉浸式的AR体验,即无论用户旋转或者移动设备来观察,虚拟物体都会位于相对于现实世界的同一个位置。
如果设置了planeDetection,ARKit会分析场景来找到现实世界中的平面。对每一个被监测到的平面,ARKit会自动添加一个ARPlaneAnchor对象到该session。
1.8-ARLightEstimate
与被捕捉的视图帧相关的分析场景的灯光数据。
如果在AR scene上覆盖其它图形,可以使用在明暗处理算法中使用这些信息来使得这些图形可以匹配现实世界的光照情况。(ARSCNView类会自动使用这些数据来配置光照)
@interfaceARLightEstimate: NSObject /**
灯光强度 范围0-2000 默认1000
*/@property(nonatomic, readonly) CGFloat ambientIntensity;
@end
1.9-ARSceneView
一个用来展示增强相机视图和3D SceneKit内容的AR体验的页面。
ARSceneView类提供了最简单的方法来创建增强了现实的体验,即将虚拟的3D内容和设备相机反映的现实世界结合起来。当运行一个由ARSession对象提供的页面时:
页面会自动的渲染有由设备相机提供的实时影像作为场景的背景。
页面的场景(scene,由SceneKit提供)的世界坐标系统会直接映射成由session configuration简历的AR世界的坐标系统。
页面会自动的移动它的SceneKit相机来匹配现实世界中设备的移动。
因为ARKit会自动将SceneKit空间匹配到现实世界,所以,放置一个虚拟物体让它能够保持现实世界的位置只需要正确地设置SceneKit的位置即可。
使用ARAnchor类来追踪添加在场景中的物体并不是必须的,但是,如果实现了ARSCNViewDelegate方法,就可以添加SceneKit内容到任一由ARKit监测到锚点上。
@interfaceARSCNView:SCNView/**
代理
*/@property(nonatomic,weak,nullable)id delegate;/**
AR会话
*/@property(nonatomic,strong) ARSession *session;/**
场景
*/@property(nonatomic,strong)SCNScene*scene;/**
是否自动适应灯光
*/@property(nonatomic)BOOLautomaticallyUpdatesLighting;/**
返回对应节点的锚点,节点是一个3D虚拟物体,它的坐标是虚拟场景中的坐标,而锚点ARAnchor是ARKit中现实世界的坐标。
*/- (nullableARAnchor *)anchorForNode:(SCNNode*)node;/**
返回对应锚点的物体
*/- (nullableSCNNode*)nodeForAnchor:(ARAnchor *)anchor;/**
根据2D坐标点搜索3D模型,这个方法通常用于,当我们在手机屏幕点击某一个点的时候,可以捕捉到这一个点所在的3D模型的位置,至于为什么是一个数组非常好理解。手机屏幕一个是长方形,这是一个二维空间。而相机捕捉到的是一个由这个二维空间射出去的长方体,我们点击屏幕一个点可以理解为在这个长方体的边缘射出一条线,这一条线上可能会有多个3D物体模型
point:2D坐标点(手机屏幕某一点)
ARHitTestResultType:捕捉类型 点还是面
(NSArray *):追踪结果数组 详情见本章节ARHitTestResult类介绍
数组的结果排序是由近到远
*/- (NSArray *)hitTest:(CGPoint)point types:(ARHitTestResultType)types;@end//代理#pragma mark - ARSCNViewDelegate//代理的内部实现了SCNSceneRendererDelegate:scenekit代理 和ARSessionObserver:ARSession监听(KVO机制)
@protocolARSCNViewDelegate@optional/**
自定义节点的锚点
*/- (nullableSCNNode*)renderer:(id)renderer nodeForAnchor:(ARAnchor *)anchor;/**
当添加节点是会调用,我们可以通过这个代理方法得知我们添加一个虚拟物体到AR场景下的锚点(AR现实世界中的坐标)
*/- (void)renderer:(id)renderer didAddNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor;/**
将要刷新节点
*/- (void)renderer:(id)renderer willUpdateNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor;/**
已经刷新节点
*/- (void)renderer:(id)renderer didUpdateNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor;/**
移除节点
*/- (void)renderer:(id)renderer didRemoveNode:(SCNNode*)node forAnchor:(ARAnchor *)anchor;
@end
1.10-SRSKView
展示2D内容,与ARSceneView类似,这里不做重复介绍。
1.11-ARHitTestResult
通过分析一个点在一个AR session中的设备相机视图而获得的现实平面的信息。
如果使用SceneKit或者SpiriteKit来展示一个AR体验,可以使用以下方法来搜索位于视图某一点的现实世界内容的相机图像:
ARSCNView hitTest:types:
ARSKView hitTest:types:
另外,使用ARFrame hitTest:types:方法可以搜索现实世界内容的相机图像。由于frame是独立于view的,对于这个方法来说,你所传递的点是标准化过的图像坐标,即坐标范围为(0,1)。
这些方法会返回一个ARHitTestResult对象的数组来描述找到的内容。
//捕捉类型枚举typedefNS_OPTIONS(NSUInteger, ARHitTestResultType) {/** 点. */ARHitTestResultTypeFeaturePoint = (1<<0),/** 水平面 y为0. */ARHitTestResultTypeEstimatedHorizontalPlane = (1<<1),/** 已结存在的平面. */ARHitTestResultTypeExistingPlane = (1<<3),/** 已结存在的锚点和平面. */ARHitTestResultTypeExistingPlaneUsingExtent = (1<<4),}NS_SWIFT_NAME(ARHitTestResult.ResultType);/**
捕捉类型
*/@property(nonatomic,readonly) ARHitTestResultType type;/**
3D虚拟物体与相机的距离(单位:米)
*/@property(nonatomic,readonly)CGFloatdistance;/**
本地坐标矩阵(世界坐标指的是相机为场景原点的坐标,而每一个3D物体自身有一个场景,本地坐标就是相对于这个场景的坐标)类似于frame和bounds的区别
*/@property(nonatomic,readonly) matrix_float4x4 localTransform;/**
世界坐标矩阵
*/@property(nonatomic,readonly) matrix_float4x4 worldTransform;/**
锚点(3D虚拟物体,在虚拟世界有一个位置,这个位置参数是SceneKit中的SCNVector3:三维矢量),而锚点anchor是这个物体在AR现实场景中的位置,是一个4x4的矩阵
*/@property(nonatomic,strong,nullable,readonly) ARAnchor *anchor;
@end
各个类之间的交互流程:
ARCamera捕捉现实视图,并把其信息交由ARSession处理。ARCamera捕获的数据是一个一个的ARFrame构成。
ARSession类会管理对现实世界的追踪和移动,并整合和建立现实世界和虚拟世界的对应关系,它追踪的内容由ARSessionConfiguration来决定。它会将ARCamera捕获到的数据转化成虚拟世界可展示的数据交给ARSceneView。
一个基于SceneView的ARSceneView以现实视图为背景,展示SceneView形成的3D物体,其中的展示现实视图的数据就是从ARSession获得,每一个虚拟物体的场景(Scene)都对应一个ARSession类。
ARSceneView作为SceneView的子类,是由一个一个的节点(node)组成,当从ARSession获得现实视图的相应数据后,ARSceneView会构成相应节点并将其作为根节点(背景)。