如何在现实场景中随心放置AR虚拟对象?
随着AR的发展和电子设备的普及,人们在生活中使用AR技术的门槛降低,比如对于不方便测量的物体使用AR测量,方便又准确;遇到陌生的路段使用AR导航,清楚又便捷;网购时拿不准的物品使用AR购物,体验更逼真。
想要让虚拟物体和现实世界相融合,重要的一步就是将虚拟对象准确放置在现实场景中,当用户触摸电子屏幕上的任意地方时即可创建AR对象,达到良好的交互体验。
华为HMS Core AR Engine持续跟踪设备相对于周围环境的位置和姿态变化轨迹,建立虚拟数字世界和现实物理世界的统一几何空间,为您的应用提供虚实融合的交互基础平台。其中命中检测技术让用户可通过点击终端设备屏幕选中现实环境中的兴趣点,终端设备屏幕上的兴趣点映射为现实环境中的兴趣点,并以兴趣点为源发出一条射线连接到摄像头所在位置,返回这条射线贯穿的任何平面或特征点以及交叉位置在现实世界空间中的位置和姿态。命中检测与平面碰撞,获得碰撞点的位置及法向量,让用户可以自由选择环境中的物体或者与它们互动。
Demo

开发步骤
开发环境要求:
JDK 1.8.211及以上。
安装Android Studio 3.0及以上:
minSdkVersion 26及以上
targetSdkVersion 29(推荐)
compileSdkVersion 29(推荐)
Gradle 6.1.1及以上(推荐)
在华为终端设备上的应用市场下载AR Engine服务端APK(需在华为应用市场,搜索“华为AR Engine”)并安装到终端设备。
测试应用的设备:参见AREngine特性软硬件依赖表中环境Mesh支持设备列表。如果同时使用多个HMS Core的服务,则需要使用各个Kit对应的最大值。
开发准备
在开发应用前需要在华为开发者联盟网站上注册成为开发者并完成实名认证,具体方法请参见帐号注册认证。
华为提供了Maven仓集成方式的AR Engine SDK包,在开始开发前,需要将AR Engine SDK集成到您的开发环境中。
Android Studio的代码库配置在Gradle插件7.0以下版本、7.0版本和7.1及以上版本有所不同。请根据您当前的Gradle插件版本,选择对应的配置过程。
以7.0为例:
打开Android Studio项目级“build.gradle”文件,添加Maven代码库。
在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。
buildscript {repositories {google()jcenter()maven {url "https://developer.huawei.com/repo/" }}
}
打开项目级“settings.gradle”文件,配置HMS Core SDK的Maven仓地址
dependencyResolutionManagement {repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)repositories {repositories {google()jcenter()maven {url "https://developer.huawei.com/repo/" }}}
}
- 添加依赖 在“dependencies”中添加如下编译依赖:
dependencies {implementation 'com.huawei.hms:arenginesdk:{version}
}
开发步骤
- 首先创建WorldRenderManager,这个类提供了与世界场景相关的渲染管理,包括标签渲染和虚拟对象渲染管理。
public class WorldRenderManager implementsGLSurfaceView.Renderer{//此方法构造函数传递上下文public WorldRenderManager(Activity activity, Context context) {mActivity = activity;mContext = context;…
}
//此方法设置ARSession,它将更新并获取OnDrawFrame中的最新数据。
public void setArSession(ARSession arSession) {if (arSession == null) {LogUtil.error(TAG, "setSession error, arSession is null!");return;}mSession = arSession;}
//设置ARWorldTrackingConfig,获取配置模式。
public void setArWorldTrackingConfig(ARWorldTrackingConfig arConfig) {if (arConfig == null) {
LogUtil.error(TAG, "setArWorldTrackingConfig error, arConfig is null!");return;}mArWorldTrackingConfig = arConfig;}
//实现onDrawFrame方法
@Override
public void onDrawFrame(GL10 unused) {mSession.setCameraTextureName(mTextureDisplay.getExternalTextureId());
ARFrame arFrame = mSession.update();
ARCamera arCamera = arFrame.getCamera();
…….
}
//命中结果输出
private ARHitResult hitTest4Result(ARFrame frame, ARCamera camera, MotionEvent event) {ARHitResult hitResult = null;List<ARHitResult> hitTestResults = frame.hitTest(event);
//确定命中点是否在平面多边形内。
ARHitResult hitResultTemp = hitTestResults.get(i);if (hitResultTemp == null) {continue;}
ARTrackable trackable = hitResultTemp.getTrackable();//确定点云是否被单击,以及点是否面向相机。boolean isPointHitJudge = trackable instanceof ARPoint
&& ((ARPoint) trackable).getOrientationMode() == ARPoint.OrientationMode.ESTIMATED_SURFACE_NORMAL;
//优先选择平面上的点。
if (isPlanHitJudge || isPointHitJudge) {hitResult = hitResultTemp;if (trackable instanceof ARPlane) {break;}}
return hitResult;
}
}
- 创建WorldActivity,本AR示例介绍了如何使用HUAWEI AR Engine的世界AR场景。
public class WorldActivity extends BaseActivity {private ARSession mArSession;
private GLSurfaceView mSurfaceView;
private ARWorldTrackingConfig mConfig;
@Override
protected void onCreate(Bundle savedInstanceState) {LogUtil.info(TAG, "onCreate");super.onCreate(savedInstanceState);setContentView(R.layout.world_java_activity_main);mWorldRenderManager = new WorldRenderManager(this, this);
mWorldRenderManager.setDisplayRotationManage(mDisplayRotationManager);
mWorldRenderManager.setQueuedSingleTaps(mQueuedSingleTaps)
}
@Override
protected void onResume() {if (!PermissionManager.hasPermission(this)) {this.finish();}errorMessage = null;if (mArSession == null) {try {if (!arEngineAbilityCheck()) {finish();return;}mArSession = new ARSession(this.getApplicationContext());mConfig = new ARWorldTrackingConfig(mArSession);refreshConfig(ARConfigBase.LIGHT_MODE_ENVIRONMENT_LIGHTING | ARConfigBase.LIGHT_MODE_ENVIRONMENT_TEXTURE);} catch (Exception capturedException) {setMessageWhenError(capturedException);}if (errorMessage != null) {stopArSession();return;}
}@Overrideprotected void onPause() {LogUtil.info(TAG, "onPause start.");super.onPause();if (mArSession != null) {mDisplayRotationManager.unregisterDisplayListener();mSurfaceView.onPause();mArSession.pause();}LogUtil.info(TAG, "onPause end.");}
@Overrideprotected void onDestroy() {LogUtil.info(TAG, "onDestroy start.");if (mArSession != null) {mArSession.stop();mArSession = null;}if (mWorldRenderManager != null) {mWorldRenderManager.releaseARAnchor();}super.onDestroy();LogUtil.info(TAG, "onDestroy end.");}
…..
}
了解更多详情>>
访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解 HMS Core 最新技术资讯~
相关文章:
如何在现实场景中随心放置AR虚拟对象?
随着AR的发展和电子设备的普及,人们在生活中使用AR技术的门槛降低,比如对于不方便测量的物体使用AR测量,方便又准确;遇到陌生的路段使用AR导航,清楚又便捷;网购时拿不准的物品使用AR购物,体验更…...
操作系统-处理机调度
1.处理机调度的概念、层次1.1调度的基本概念制定某种规则来决定处理任务的顺序。1.2调度的三个层次高级调度(作业调度)中级调度(内存调度)进程的挂起态与七状态模型低级调度(进程调度)小结2.进程调度的时机…...
手机截图如何提取文字?
在当今信息爆炸的时代,图文并茂已经成为了一个广告宣传的常用方式。然而,图片中的文字信息往往难以获取,尤其对于那些需要快速获取信息的人们来说,阅读图片中的文字会是一项繁琐且费时的任务。现在,我们有一个好消息要…...
vue中复制内容
vue中复制内容vue2vue-clipboard2依赖项在main.js引入使用vue3vue-clipboard3依赖项引入使用更新于:2023-02-15vue2vue-clipboard2 依赖项 “vue”: “^2.6.11” “vue-clipboard2”: “^0.3.1” 在main.js引入 import VueClipboard from vue-clipboard2 Vue.us…...
MySQL CAST()函数用法
一、语法 expr:源数据,如字符串’China’。type:目标数据类型,例如CHAR。 cast(expr AS type)二、命令说明 将任何类型的值转换为具有指定类型的值。 CAST()函数通常用于返回具有指定类型的值,以便在WHEREÿ…...
【测试工程师面试】详细记录 自己的一次面试
【测试工程师面试】详细记录 自己的一次面试 目录:导读 Linux基础 Oracle基础 编程基础 测试的基础 面试的问题 扯闲话部分: 10点刚到,先进行笔试,笔试的题目很基础,涉及到linux,涉及到oracle数据库…...
Elasticsearch 安装(二)
目录前言一、Linux 安装1、下载安装包⑴、选择需要的安装包⑵、下载解压到安装目录2、查看解压后目录结构3、启动 Elasticsearch⑴、正常启动流程⑵、启动过程遇到的问题①、启动报错②、创建运行 Elasticsearch 的用户,启动成功,但无法访问③、停止Elas…...
Java基础:异常与错误(ExceptionError)
1 缘起 某天上网冲浪时,偶然看到一个问题,说Java的Error和Exception有什么区别? 一句话:不知道。并不能很清晰地描述出个中区别。 当然,曾经也看过Throwable相关的知识,但是,并没有通过源码及注…...
VAmPI:一个包含了OWASP Top10漏洞的REST API安全学习平台
关于VAmPI VAmPI是一个包含了OWASP Top10漏洞的REST API安全学习平台,该平台基于Flask开发,该工具的主要目的是通过一个易受攻击的API来评估针对API安全检测工具的有效性,并帮助广大研究人员学习和了解API安全。 功能介绍 1、基于OWASP Top…...
springboot(6)之前端传递参数的方式 普通 集合 数组
实体类传递 首先我们在后端定义一个实体类,通过lombok插件重写 有参 无参 get set toString 方法, 然后前端发送数据,后端就会自动收到,然后属性填写 后端代码如下 AllArgsConstructor Data NoArgsConstructor public class role …...
redis分布式锁的演变过程
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、直接添加Redis缓存二、使用setnx执行抢锁过程三、setnx获取锁+设置过期时间四、引入UUID解决误删锁问题五、引入Lua脚本来做删除六、对递归部分优化进行自旋七、添加自旋次数八、改为重入锁,使…...
leaflet 修改popup的样式,个性化弹窗(069)
第069个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中修改popup组件的样式,个性化弹窗。主要方法是更改css, 中增加custom-popup类名,style的样式要做穿透处理 >>>.具体方法请参考源代码。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实…...
注解ConfigurationProperties、EnableConfigurationProperties的用法
1 ConfigurationProperties ConfigurationProperties主要作用就是将prefix属性指定的前缀配置项的值绑定到这个JavaBean上 ,通过指定的前缀,来绑定配置文件中的配置。这样的好处是将配置数据与JOPO进行转换,能够管理一个类别的所有配置信息&…...
自适应布局之淘宝无限适配+rem+微信rpx自适应
一、自适应布局 所谓前端适配,就是为了让移动设计稿在大部分的移动设备上看起来有一致的展示效果,目前比较流行的方法有两种。一种是强制meta viewport宽度为设计稿宽度,一种是使用rem自适应布局的flexible.js。 二、当前流行的移动端自适应…...
esxi不能识别不兼容网卡解决方案
相信很多网友在安装测试VMWARE Esxi 6.0的时候,总会遇到无法兼容网卡的情况,本人也是遇到了再组装的台式机上测试ESXI 6.0的时候,无法识别REALTEK RTL 8111E的情况。 找了很多网友提供的博客,方法是正确的,但是不够严…...
Sizeof与Strlen的区别与联系
16年写了很多 C 与 C 相关的文章,但是后面从事了 Android 开发,就全部删掉了,无意中发现了这篇由还存在草稿箱,索性就找回来吧,也是追忆当年学习的青葱岁月 Sizeof与Strlen的区别与联系 一、sizeof sizeof(…)是运算…...
力扣(LeetCode)413. 等差数列划分(2023.02.15)
如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。 例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。 给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的 子数组 个数。 …...
蓝桥杯刷题——基础篇(一)
这部分题目,主要面向有志参加ACM与蓝桥杯竞赛的同学而准备的,蓝桥杯与ACM考察内容甚至评测标准基本都一样,因此本训练计划提供完整的刷题顺序,循序渐进,提高代码量,巩固基础。因竞赛支持C语言、C、Java甚至…...
Java基础知识快速盘点(三)
一,构造器 创建一个类的方法时会调用该类的构造器 构造器,也叫构造方法 构造器是属于类的,对象不可调用 构造方法没有返回值类型 构造方法一般用public修饰,也可用private修饰,例如 public class Test {private T…...
vscode编程小插件之Doxygen和Better Align
一、插件Doxygen:配置相应文件、函数说明项。 1、扩展商店,搜索Doxygen,如下图1,安装。 图1 2、设置项中,选择扩展设置,如图2 图2 3、配置版本、作者邮箱、作者名称、日期格式等等,如图3 4、定义函数后&…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
