Before VisionOS: AR场景下实现手势识别交互-ARKit + RealityKit + VisionKit

我正在参加「掘金·启航计划」

引言

6月21日苹果发布了Xcode 15 beta 2,包含了VisionOS 1 beta,在正式进入VisionOS的开发前,我将通过一个简单的demo,讲解一下苹果与AR相关的几个原生框架的使用以及其中的核心概念。

image.png

Demo 演示
(ARKit识别平面,RealityKit添加水平面、前左右三面墙、彩球,发射白球,处理碰撞检测,VisionKit检测手指发射白球)

20230622143332321.GIF

ARKit基础

AR是英文Augmented Reality的缩写,意为增强现实,而VR Virtual Reality为虚拟现实。AR强调的是对真实世界的增强,而VR是脱离了真实世界创造的虚拟世界,微软提出的MR(Mixed Reality)混合现实,是融合真实和虚拟世界的技术,强调物理实体和数字对象共存并实时相互作用,如虚实遮挡等。所以说Apple Vision Pro是一款MR设备,而非纯AR或者VR设备。

AR技术的基础是对真实环境的定位与跟踪,从而进行3D重建以完成虚拟对象与真实物体的融合、遮挡及碰撞等仿真处理。而定位与跟踪技术主要依赖于视觉惯性里程计和惯性导航系统,直白地讲主要依赖陀螺仪、加速度计以及其他图像处理相关的元器件和cv算法,两者并行作用、相互校验互补。

但是相机感光元器件和加速度计、陀螺仪都是对温度敏感的元器件,这也就是为什么初代ARKit下的AR应用中长时间使用后会出现模型漂移的现象。而图像算法无法从光滑、无纹理、反光的表面提取特征值,从而无法构建对环境的理解和检测识别平面。为解决这一问题,苹果在iphone 12 pro以上pro设备配备了LiDAR传感器(Light identification Detection And Ranging激光探测与测距),不受弱纹理的影响,能够实时精准高效地重建场景几何。

深度相机的引入虽然可以加深对环境的理解,但是因为来自太阳光的红外散射会过滤掉深度相机中的红外线,所以在户外并不能正常运行,我想这也是Vision Pro呈现的都是室内的使用场景的原因之一。

ARKit

ARKit发布于2017年WWDC,支持最低版本为iOS 11,设备为iphone6s(A9处理器)及以上设备。ARKit提供的功能总体可以分为三个部分:运动跟踪、场景理解、渲染。

运动跟踪、场景理解上我们无需关注细节,在API层面ARKit中的ARSession给我们提供了打开摄像头去检测、跟踪当前环境(空间、平面、人脸、图片、物体)的能力。

严格来讲ARKit并没有渲染的能力,在ARKit 1版本到RealityKit推出之前,AR的渲染需要依赖其他第三方渲染框架,如3D SceneKit、2D SpirteKit、Metal或者自定义渲染器,这得益于ARKit提供连续的摄像头图像流,可以方便的对接其他渲染。

image.png

追溯SceneKit的源头,它是苹果最初在mac上用于3D渲染的框架,其初衷并不是为了AR而设计,或者说3D渲染并不能满足AR的渲染,要做到对现实的增强而不产生割裂感,需要支持PBR、运动模糊、环境光估计、环境反射等,所以苹果在2019年发布了为AR渲染量身打造的RealtyKit框架,重点解决现实环境中的虚拟元素PBR渲染以及精准的行为模拟。从而形成了ARAPP = ARKit提供环境数据 + RealityKit渲染的新局面。

image.png

RealityKit

RealityKit发布于2019年,只支持iOS 13以上系统,而iOS13同时也是支持SwiftUI的起点,所以苹果推荐的使用方式就是RealityKit + SwiftUI的方式,而VisionOS同样是需要与SwiftUI的界面搭建配合。(也意味着开发者需要去使用swift、swiftUI、以及iOS13以上新的API了,还在适配iOS13以下系统的小伙白,是时候跟相关负责人谈一谈了。)

image.png

RealityKit包含四类实体:ARView、Scene、Anchor、Entity,AR应用中的所有虚拟元素都是以实体的形式存在,其中ARView是进入AR世界的入口,在创建ARView时会自动创建一个Scene,而Scene是放置所有实体对象的容器,实体的添加需要指定在空间中的锚点,即AnchorEntity,用于在现实空间与虚拟之间建立关联关系,在添加AnchorEntity后再将实体对象添加到AnchorEntity形成层级关系。

image.png

RealityKit的亮点

RealityKit的发布时间从AR的布局来看相对较晚或者说较新,新的框架苹果一般都加入了很多现代性的设计,如支持Combine、实体组件模式等。

  • 实体组件系统ESC:RealityKit引入了完整的实体组件系统(Entity Component System),即插即用的组件风格极大地避免了多层继承和完全杜绝了多继承带来的维护问题。Entity本身不具有外观和功能,通过挂载不同的组件而形成不同的表现和行为特性,如TransformComponent组件包含了虚拟元素在现实空间中的位置、缩放等信息。CollisionComponent则定义了虚拟元素与其他物体发生碰撞的细节。

Entity默认挂载了TransformComponent和SynchronizationComponent(用于不同设备之间同步数据),AnchorEntity默认还挂载了AnchoringComponent所以才能够添加到Scene的anchors中。

image.png

  • 网络同步:RealityKit完全整合了Multipeer Connectivity近距离通信框架,对AR应用提供内建的数据同步支持,使现实世界数据信息与整个虚拟元素信息能够在所有参与方之间实时共享。

  • 支持Combine的事件系统:同样是在2019年,苹果推出了声明性异步时间处理框架Combine,使用它可以集成事件处理代码并消除嵌套闭包和基于约定的回调。其核心为Publisher(发布者)、Operator(操作符)、Subscriber(订阅者)。RealityKit提供了对场景状态、动画播放、音频播放、碰撞事件、网络同步等变化事件的订阅支持。

VisionKit

有了ARKit的和RealityKit就已经能够开发完整的AR应用了,这里介绍VisionKit是因为AR场景下的手势交互可以使用VisionKit框架来完成。

VisionKit是苹果的计算机视觉框架,包含了文字识别、手指关节点检测、人体关节点检测等功能。遗憾的是内部高度封装,开发者能够调用的API不多,这里简单讲解一下VisionKit的三要素:

  • Request:定义请求特征来请求框架检测内容。
  • Handler:请求完成执行或处理请求之后执行的回调。
  • Observation:获得潜在的结果或观察结果,这些观察基于请求的VNObservation的实例。

Demo核心代码

ARKit + RealityKit

ARKit检测水平面:

    let config = ARWorldTrackingConfiguration()
    config.planeDetection = .horizontal
    // 启用环境纹理贴图和人形遮挡
    config.environmentTexturing = .automatic
    arView.session.delegate = self
    coachingOverlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    coachingOverlay.session = arView.session
    coachingOverlay.goal = .horizontalPlane
    coachingOverlay.frame = arView.frame
    arView.session.run(config, options: [])
    arView.addSubview(coachingOverlay)

在ARSession的回调中添加背景墙和球体Entity,这里统一使用ModelEntity,它默认挂载了ModleComponent、CollisionComponent、PhysicsBodyComponent和PhysicsMotionComponent组件,拥有物理模拟和碰撞的能力,符合我们的要求。

    public func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
    // 添加四周背景墙
    let shap : ShapeResource = .generateBox(width: 0.1, height: 1.2, depth: 3)
    let meshSphere: MeshResource = .generateBox(width: 0.1, height: 1.2, depth: 3)
    let material = SimpleMaterial(color:.red,isMetallic: **false**)
    let wallEntity = ModelEntity(mesh: meshSphere, materials: [material2], collisionShape: shap, mass: 0.04)
    wallEntity.physicsBody?.mode = .static
    wallEntity.physicsBody?.material = .generate(friction: 1, restitution: 0.01)
    wallEntity.transform.translation = [planeEntity.transform.translation.x-0.5,planeEntity.transform.translation.y+0.5, 0]
    wallEntity.name = "wall"
    planeAnchor.addChild(wallEntity)
    }
    // 添加待碰撞彩球
    ...
    

这里需要讲解一下刚体的物理属性,即physicsBodyMode:

  • .static 为永远不会移动,我们AR场景中的底部,和四周的背景墙的就是这个属性。
  • .kinematic 用户控制身体运动,可以理解为角色类游戏中你操作的移动的角色。
  • .dynamic 力和碰撞控制物体进行运动,也就是AR场景下的发射的小球的属性。

碰撞检测

    // 订阅碰撞事件 Combine框架
    subscribes.append(scene.subscribe(to: CollisionEvents.Began.self, on: fireBallEntity) { event in
        if (A.name == "box" && B.name == "ball") || (B.name == "box" && A.name == "ball") {
        if A.name == "box" {
            A.name = "score"
            A.model?.materials = [SimpleMaterial(color: .black, isMetallic: **false**)]
            score = score + 1
            scoreLabel.text = "得分\(score)"
        }
        if B.name == "box" {
            B.name = "score"
            B.model?.materials  = [SimpleMaterial(color: .black, isMetallic: false)]
            score = score + 1
            scoreLabel.text = "得分\(score)"
        }
        }
    })

发射

发射只需要在小球实体添加一个力,设置方向和方向的参考实体即可。

fireBallEntity.addForce([0,8,-40], relativeTo: planeEntity)

End

本文只是粗略介绍一部分框架的核心概念,之前的AR应用的生态相对来说还不成熟,从市面上的AR落地场景来看,大家也只是做了简单的尝试(拍摄器AR特效、AR拜年、AR地图找人/店/路、AR试鞋、AR小游戏等),随着VisionOS framework的发布,期待一些有意思有价值的应用的出现。。。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MY0pDrgh' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片