【iOS ARKit】手动配置环境探头

        在上节中我们已经了解了环境探头以及如何使用自动环境探头,这节一起了解如何使用手动配置环境探头。

     在使用自动环境反射时,开发人员无须进行有关环境反射的任何操作,只需要设置自动环境反射即可,其余工作完全由 RealityKit 自动完成,这适用于基本的常见环境反射。但这种环境反射方案是一种普适性的反射,并没有专门针对某特定虚拟元素进行优化,在某些情况下效果并不精细,并且我们也无法进行干预调优,如一辆行驶的赛车对环境的反射就需要更精细的控制,这时就需要手动控制环境探头的生成及更新。

     使用手动控制环境探头时,我们需要将配置中 environmentTexturing 属性设置为 manual,并决定在什么地方、什么时候设置与更新环境探头。通常而言,可以遵循以下流程:

(1) 在场景中某个特定位置创建 AREnvironmentProbeAnchor 锚点。

(2)将创建的 AREnvironmentProbeAnchor 锚点添加到 ARSession 中。

(3)使用 session(_:didUpdate:)代理方法根据需要更新环境探头。

使用手动方式控制环境探头的示例代码如下所示。

//
//  ManualEnvirmentTexturing.swift
//  ARKitDeamo
//
//  Created by zhaoquan du on 2024/1/30.
//import SwiftUI
import ARKit
import RealityKitstruct ManualEnvirmentTexturing: View {@State var automatic: Bool = truevar body: some View {ManualEnvirmentTexturingContainer(automatic: $automatic).overlay(content: {VStack {Spacer()HStack{Text(automatic ? "HDR" : "HDR Off").background(GeometryReader{ _ inColor.white}).padding(10).offset(x: 0)Toggle(isOn: $automatic) {}.frame(width: 50).offset(x: 0)}Spacer().frame(height: 40)}}).edgesIgnoringSafeArea(.all).navigationTitle("环境探头")}}struct ManualEnvirmentTexturingContainer:UIViewRepresentable {@Binding var automatic: Boolfunc makeUIView(context: Context) -> ARView{let arView = ARView(frame: .zero)return arView}func updateUIView(_ uiView: ARView, context: Context) {let config = ARWorldTrackingConfiguration()config.planeDetection = .horizontalconfig.environmentTexturing = .manualcontext.coordinator.arView = uiViewuiView.session.delegate = context.coordinatorif automatic {config.wantsHDREnvironmentTextures = true}else{config.wantsHDREnvironmentTextures = false}uiView.session.run(config, options: [])}func makeCoordinator() -> Coordinator {Coordinator(parent: self)}class Coordinator: NSObject,ARSessionDelegate {var manualProbe: ManualProbe?var arView: ARView? = nilvar parent: ManualEnvirmentTexturingContainerinit(parent: ManualEnvirmentTexturingContainer) {self.parent = parent}func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {guard let anchor = anchors.first as? ARPlaneAnchor else {return}//球体let mesh = MeshResource.generateSphere(radius: 0.05)let meterial = SimpleMaterial(color: .blue, isMetallic: true)let modelEntity = ModelEntity(mesh: mesh, materials: [meterial])let planAnchor = AnchorEntity(anchor: anchor)//放在正上方5cm处modelEntity.transform.translation = [0, planAnchor.transform.translation.y + 0.05,0]manualProbe = ManualProbe(shpereEntity: modelEntity)updateProbe()planAnchor.addChild(manualProbe!.shpereEntity)arView?.scene.addAnchor(planAnchor)//只添加一次session.delegate = nilsession.run(ARWorldTrackingConfiguration())manualProbe?.isPlaced = true}func session(_ session: ARSession, didUpdate frame: ARFrame) {if let manualProbe = manualProbe,manualProbe.requireRefresh,Date().timeIntervalSince1970 - manualProbe.lastUpadateTime > 1{self.manualProbe?.lastUpadateTime = Date().timeIntervalSince1970updateProbe()}}func  updateProbe() {guard let manualProbe = manualProbe else {return}//移除旧的if let probAnchor = manualProbe.objectProbeAnchor {self.arView?.session.remove(anchor: probAnchor)self.manualProbe?.objectProbeAnchor = nil}var extent = (manualProbe.shpereEntity.model?.mesh.bounds.extents)! * manualProbe.shpereEntity.transform.scaleextent.x *= 3extent.y *= 3extent.z *= 2//            let verticalOffset = SIMD3(0, extent.y, 0)
//            var probeTransform = manualProbe.shpereEntity.transform
//            probeTransform.translation += verticalOffsetlet  position = simd_float4x4(SIMD4(1,0,0,0),SIMD4(0,1,0,0),SIMD4(0,0,1,0),SIMD4(manualProbe.shpereEntity.transform.translation,1))self.manualProbe?.objectProbeAnchor = AREnvironmentProbeAnchor(name: "objectProbe",transform: position, extent:extent)self.arView?.session.add(anchor: (self.manualProbe?.objectProbeAnchor)!)}}}struct ManualProbe {var objectProbeAnchor: AREnvironmentProbeAnchor?var requireRefresh = truevar lastUpadateTime = Date().timeIntervalSince1970var dateTime = Date()var shpereEntity: ModelEntityvar isPlaced = false
}

       在代码中,为更好地组织代码,我们自定义了 ManualProbe 类管理环境探头。在 ARKit 检测到水平平面并放置圆球后,将生成的环境探头放置在園球上方5cm 的地方以更精准地反射圆球的周边环境。在 session(_:didUpdate:)代理方法中我们对环境探头更新率进行了控制,设置为每秒更新一次,与所有的 ARAnchor一样,AREnvironmentProbeAnchor 锚点无法修改,更新时只能移除原锚点信息,创建新的锚点使用。updateProbe()方法负责所有的环境探头更新操作(具体细节稍后详述)。通过及时地更新就能反射用户环境中动态的变化,效果如图所示。

       手动放置环境探头主要是为了获得对特定虚拟对象的最精确环境反射信息,绑定环境探头与虚拟对象位置可以提高反射渲染的质量,因此,手动将反射探头放置在重要的虚拟对象中或其附近会产生为该对象生成最准确的环境反射信息。通常而言,自动放置可以提供对真实环境比较好的宏观环境信息,而手动放置能提供在某个特定点上对周围环境更准确的环境映射从而提升反射的质量。

      反射探头负责捕获环境纹理信息,每个反射探头都有一个比例(Scale)、方向(Orientation)、位置(Position) 和大小(Size)。比例、方向和位置属性定义了反射探头相对于 ARSession 空间的空间信息,大小则定义了反射探头反射的范围,无限大小表示环境纹理可用于全局,而有限大小表示反射探头只能捕获其周围特定区域的环境信息。

在手动放置时,为了使放置的反射探头能更好地发挥作用,通常反射探头的放置位置与大小设置应遵循以下原则:

(1)反射探头的位置应当放在需要反射的虚拟物体顶部中央,高度应该为虚拟物体高的两倍,如下图所示。这可以确保反射探头下部与虚拟物体下部对齐,并捕获到虚拟物体放置平面的环境信息。

(2)反射探头的长与宽应该为虚拟物体长与宽的3倍,确保反射探头能捕获到虚拟物体周边的环境信息。

  • 提示:使用手动处理环境反射时,我们也可以使用 wantsHDREnvironmentTextures 提高反射质量。

性能优化

       在AR 中使用反射探头反射环境可以大大增强虚拟物体的可信度,但由于AR摄像头获取的环境信息不充分,ARKit 只能得到摄像头拍摄的真实环境部分数据,而无法获取摄像头未拍摄部分的环境数据,需要利用人工智能的方式对不足信息进行补充,需要补充的信息计算量大,对资源要求高,这对移动平台的性能与电池续航提出了非常高的要求,因此为更好的扬长避短,在AR 中使用反射探头反射真实环境需要注意以下几点。

1. 避免精确反射

     如上所述,AR中从摄像头获取的信息不足以对周围环境进行精准再现,因此反射体对环境的反射也不能做到非常精准,希望利用反射探头实现对真实环境的镜面反射是不现实的。因为在 AR 中不能获取完全的立方体贴图并且立方体贴图更新也不实时(为降低硬件消耗),通常在小面积上可以使用高反射率而在大面积上使用低反射率,达到既营造反射效果又避免反射不准确而带来的负面作用。

2. 对移动对象的处理

     烘焙的环境贴图不能反映环境的变化,实时的反射探头又会带来过大的性能消耗,对移动对象的反射处理需要特别进行优化。在设置反射探头时可以考虑以下方法:

(1)如果移动物体移动路径可知或可以预测,可以提前在其经过的路径上放置多个反射探头并进行烘焙,这样移动物体可以根据距离的远近对不同的反射探头生成的立方体贴图采样。

(2)创建一个全局的环境反射,如Skybox,这样当移动物体移动出某个反射探头的范围时仍然可以反射而不是突然出现反射中断。

(3)当移动物体移动到一个新的位置后重新创建一个反射探头并销毁原来位置的反射探头。

3. 防止滥用

     在AR中,当用户移动位置或者调整虚拟对象大小时,应用程序都会重新创建反射探头,因此我们需要限制此类更新,如更新频率不应大于1次每秒。

4.避免突然切换

      突然地移除反射探头或者添加新的反射探头会让用户感到不适。在 ARKit 中使用自动放置反射探头的模式下,只要 ARSession启动,就会创建一个全局的类似 Skybox 的大背景以防止反射突然切换。在手动放置时,开发者应该确保反射的自然过渡,确保虚拟物体始终能反射合适的环境,或者使用一个全种环境下都能适应的静态立方体贴图作为过渡手段。

具体代码地址:https://github.com/duzhaoquan/ARkitDemo.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669241.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【django】建立python虚拟环境-20240205

1.确保已经安装pip3 install venv 2.新建虚拟环境 python -m venv myenv 3.安装虚拟环境的依赖包 pip install … 4.激活虚拟环境 cd myenv cd Scripts activate 激活activate.bat并进入虚拟环境 进入虚拟环境后,命令行前面显示(myenv&#xff0…

如何以管理员身份删除node_modules文件

今天拉项目,然后需要安装依赖,但是一直报错,如下: 去搜这个问题会让把node_modules文件先删掉 再去安装依赖。我在删除的过程中会说请以管理员身份来删除。 那么windows如何以管理员身份删除node_modules文件呢? wi…

HomeAssistant系统添加HACS插件商店与远程控制家中智能家居

文章目录 基本条件一、下载HACS源码二、添加HACS集成三、绑定米家设备 ​ 上文介绍了如何实现群晖Docker部署HomeAssistant,通过内网穿透在户外控制家庭中枢。本文将介绍如何安装HACS插件商店,将米家,果家设备接入 Home Assistant。 基本条件…

2024年2月CCF-全国精英算法大赛题目

第一次参加这种比赛,虽然是c类赛事,但是是ccf主办的,难度还是有点的,主要是前面签到题主要是思想,后面的题目难度太高,身为力扣只刷了一百多道题目的我解决不了,这几道我只做了B,C题,E题超时了&…

您的Google Play开发者账户的Google付款资料已被暂停!——你是否收到这封邮件?

2023年8月,google play政策更新,为保障 Google Play 用户的安全,您必须确保开发者帐号信息准确无误。否则,您在 Google Play 上的开发者资质和应用供应情况可能会受到影响。 2023年10月开始,Google Play开始正式逐步施…

大数据分析|大数据分析的十大应用领域

有许多技术可用于分析大数据。这项工作介绍了BDA适用的各种分析技术领域如下。 (1)社会分析 社交分析是实时数据分析中一个重要且不断发展的分析方法。它分为社交网络(例如,Facebook和LinkedIn),博客(例如,Blogger和W…

进程和线程的区别详解

🎥 个人主页:Dikz12📕格言:那些在暗处执拗生长的花,终有一日会馥郁传香欢迎大家👍点赞✍评论⭐收藏 目录 进程 进程在系统中是如何管理的 进一步认识PCB 线程 能否一直增加线程数目来提高效率 进程和线程…

看论文利器:paperswithcode

paperswithcode,从名字就可以看出来,有源代码的paper。 写论文,很关键的就是能够复现论文内容。 这个网站提供了“论文代码”的参考文献。 以【图像加密】领域为例,搜索一下: 图像分割: 除了论文&#x…

2024年:用OKR管理你的生活

在科技高速发展的时代,越来越多的企业和团队开始采用OKR(Objectives and Key Results)管理方法来设定目标并跟踪进度。你是否想过,将OKR理念引入个人生活,以更有效地实现人生目标?本文将探讨如何在2024年运…

Linux环境docker安装gitlab(简单粗暴,复制即用)

前言 为方便运维,本人将常用docker安装镜像方式总结如下: 一、安装gitlab 1.查询镜像 docker search gitlab2.拉取镜像 可以根据自己需求拉取想要的版本,我选的是中文版 docker pull twang2218/gitlab-ce-zh3.创建挂载路径 mkdir -p /…

list基本使用

list基本使用 构造迭代器容量访问修改 list容器底层是带头双向链表结构&#xff0c;可以在常数范围内在任意位置进行输入和删除&#xff0c;但不支持任意位置的随机访问&#xff08;如不支持[ ]下标访问&#xff09;&#xff0c;下面介绍list容器的基本使用接口。 template <…

dolist案例实现

这段代码是一个使用Vue.js实现的简单的ToDoList&#xff08;待办事项列表&#xff09;应用。我们分几个部分详细解释这段代码。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>todolist</title&g…

互联网医院|互联网医院平台让医疗更智慧更容易

近年来&#xff0c;互联网医院在我国的应用范围不断扩大。然而&#xff0c;仍有许多人和医疗机构对线上问诊小程序的推广持保留态度&#xff0c;认为其应用效果不佳、覆盖范围有限。那么&#xff0c;我们应如何充分利用互联网医院系统&#xff0c;让线上医疗发挥更大的优势呢&a…

【发票识别】新增针对图片发票的识别(升级中)

说明 为了完善发票识别的功能&#xff0c;目前发票识别支持发票图片格式的识别&#xff0c;增加可用性。 体验 体验地址&#xff1a;https://invoice.behappyto.cn/invoice-service/ 体验地址上面有示例的发票&#xff0c;可以下载上传识别或者复制url地址进行识别。 技术栈…

不下载任何插件和依赖,在线导出swagger的api接口文档(word)

一、前言 swagger是一个非常方便用来生成api的工具集&#xff0c;它提供了可视化的restful风格的web界面&#xff0c;方便查看生成的api。 但是&#xff0c;想要将swagger生成的api直接导出为doc文档&#xff0c; 似乎不太方便实现&#xff0c;解析swagger的json串&#xff0c;…

错帐的查找与更正方法

目录 一. 错帐的查找方法二 . 结账![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9dd023684fb744acbfd00ff0bf8f7ef3.png)三. 对账 \quad 一. 错帐的查找方法 \quad \quad 实际工作中常用逆查法,因差错往往出现于后期。 \quad \quad 1、差数是由于漏记、看错、抄…

使用Virt-Manager定制 Windows Server QCOW2镜像

使用Virt-Manager定制 Windows Server QCOW2镜像 前言 在云计算和虚拟化技术日益普及的今天&#xff0c;定制化的虚拟机镜像对于满足特定需求显得尤为重要。Virt-Manager是一个强大的工具&#xff0c;可以帮助用户轻松地创建和管理虚拟机镜像。本文将指导您如何使用Virt-Manag…

istio 限流

#详细参数看官网&#xff0c;我参数就不解释https://istio.io/latest/docs/reference/config/networking/destination-rule/cat << EOF > dr.yaml apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata:name: my-testnamespace: demon spec:hos…

【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现

盘点本年度探索对外服务的百万请求量的API网关设计实现 背景介绍高性能API网关API网关架构优化多级缓存架构设计多级缓存富客户端漏斗模型数据读取架构 异步刷新过期缓存网关异步化调用模型高性能批量API调用&#xff08;减少对于网关的交互和通信&#xff09;并行调用和请求合…

【论文精读】多模态情感分析 —— VLP-MABSA

Vision-Language Pre-Training for Multimodal Aspect-Based Sentiment Analysis 本篇论文发表于ACL-2022 原文链接 https://arxiv.org/abs/2204.07955 源码 GitHub - NUSTM/VLP-MABSA 模态&#xff1a;图像文本 基于多模态方面的情感分析(MABSA)近年来越来越受到关注。然而&am…