如何在现实场景中随心放置AR虚拟对象?
随着AR的发展和电子设备的普及,人们在生活中使用AR技术的门槛降低,比如对于不方便测量的物体使用AR测量,方便又准确;遇到陌生的路段使用AR导航,清楚又便捷;网购时拿不准的物品使用AR购物,体验更逼真。
想要让虚拟物体和现实世界相融合,重要的一步就是将虚拟对象准确放置在现实场景中,当用户触摸电子屏幕上的任意地方时即可创建AR对象,达到良好的交互体验。
华为HMS CoreAR 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;
}
}
@Override
protected void onPause() {
LogUtil.info(TAG, "onPause start.");
super.onPause();
if (mArSession != null) {
mDisplayRotationManager.unregisterDisplayListener();
mSurfaceView.onPause();
mArSession.pause();
}
LogUtil.info(TAG, "onPause end.");
}
@Override
protected 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虚拟对象?的更多相关文章
- 《将一个字符串转换成datetime时,先分析该字符串以获取日期,然后再将每个变量放置到datetime对象中》的解决办法
我们在写代码时,稍不注意就收到VS那文不对题的错误提示. 最近在项目上碰到了“将一个字符串转换成datetime时,先分析该字符串以获取日期,然后再将每个变量放置到datetime对象中”的这个错误提 ...
- C++中的定位放置new(placement new)
一般来说,使用new申请空间时,是从系统的“堆”(heap)中分配空间.申请所得的空间的位置时根据当时的内存的实际使用情况决定的.但是,在某些特殊情况下,可能需要在程序员指定的特定内存创建对象,这就是 ...
- 找到你的位置(JS在页面中的位置)最常用的方式是在页面中head部分放置<script>元素,浏览器解析head部分就会执行这个代码,然后才解析页面的其余部分
找到你的位置(JS在页面中的位置) 我们可以将JavaScript代码放在html文件中任何位置,但是我们一般放在网页的head或者body部分. 放在<head>部分 最常用的方式是在页 ...
- 在WebGL场景中管理多个卡牌对象的实验
这篇文章讨论如何在基于Babylon.js的WebGL场景中,实现多个简单卡牌类对象的显示.选择.分组.排序,同时建立一套实用的3D场景代码框架.由于作者美工能力有限,所以示例场景视觉效果可能欠佳,本 ...
- 【多服务场景化解决方案】AR虚拟技术助力智能家装
1 .介绍 总览 本应用采用了华为图形引擎服务的AR虚拟技术,您可以在手机相机里摆放想要购置的家具家电,交互式体验让您可以轻松操控它们的3D图例,以此来确定这些家具家电是否适合摆放在您的家里. 特 ...
- iOS 中的 block 是如何持有对象的
Block 是 Objective-C 中笔者最喜欢的特性,它为 Objective-C 这门语言提供了强大的函数式编程能力,而最近苹果推出的很多新的 API 都已经开始原生的支持 block 语法, ...
- 应用教程之帕克西AR虚拟试妆3D动态美妆
帕克西技术团队通过对美妆行业深度调研,凭借自主研发的人脸识别与面部追踪等技术,打造的超现实AR虚拟试妆应用已成功上线,内置万千妆容,包含口红.眉毛.睫毛等,一点即可试妆,就像照镜子一样简单. 那么,帕 ...
- java web学习总结(二十五) -------------------JSP中的九个内置对象
一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...
- 静态方法中不能new内部类的实例对象的总结
class Test{ public void main(String[] args){ A testA=new A(); //这里会出现问题 new Thread(new Runnable(){ p ...
- ahjesus在asp.net中还可以通过设置HttpCookie对象的过期时间为DateTime.MinValue来指定此Cookies为跟随浏览器生效
ahjesus在asp.net中还可以通过设置HttpCookie对象的过期时间为DateTime.MinValue来指定此Cookies为跟随浏览器生效
随机推荐
- 任务系统之API子任务
日常运维工作中有许多的任务要执行,例如项目发布/数据备份/定时巡检/证书更新/漏洞修复等等,大部分的任务都会有多个步骤共同完成,例如一个发布任务会有拉代码.编译.分发.通知等等步骤,而不同的任务可能还 ...
- eclipse c++ 安装
eclipse及其插件安装 对于我这种被VS惯坏了的人来说,make file 非常不友好的,最近要在redhat 下面去编译c++动态库和应用程序,原有的工程是在window下面的,要到linux下 ...
- 第134篇:解决浏览器的CORS跨域问题(CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome-untrusted, https, edge.)
好家伙, 我继续尝试着将我的飞机大战使用ES6模块化分离开来,出了点问题 1.出现问题: edge,chrome等一系列浏览器,会为了安全,禁止你跨域访问 目录如下: 主程序 index.htm ...
- 【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
Azure Spring Cloud 是什么? 借助 Azure Spring Cloud,可以轻松地将 Spring Boot 微服务应用程序部署到 Azure,不需更改任何代码. 该服务管理 Sp ...
- 如何实现十亿级离线 CSV 导入 Nebula Graph
本文首发于 Nebula Graph Community 公众号 本次实践是基于业务需求及后续扩展,通过技术选型确定了 Nebula Graph 图数据库,首先需要验证 Nebula Graph 数据 ...
- ConfigMap挂载与Subpath在Nginx容器中的应用
本文分享自华为云社区<nginx.conf以configmap文件形式挂载到nginx容器中以及subpath使用场景>,作者:可以交个朋友. 背景 nginx.conf通过configm ...
- RocketMQ(4) 消息的消费
消费者从Broker中获取消息的方式有两种:pull拉取方式和push推动方式.消费者组对于消息消费的模 式又分为两种:集群消费Clustering和广播消费Broadcasting. 1. 获取消息 ...
- CYQ.Data 支持 KingbaseES人大金仓数据库
KingbaseES人大金仓数据库介绍: KingbaseES是一种关系型数据库管理系统,也被称为人大金仓数据库.KingbaseES 是北京人大金仓信息技术股份有限公司研发的,具有自主知识产权的通用 ...
- Nginx安装nginx-rtmp-module模块
简介 nginx中的模块虽然就是类似插件的概念,但是它无法像VsCode那样轻松的安装扩展. nginx要安装其它模块必须同时拿到nginx源代码和模块源代码,然后手动编译,将模块打到nginx中,最 ...
- javascript web development es6 pdf js - Cheat Sheet 表格 [vuejs / webcomponents-cheatsheet-2021] 共3套
ES6 预览 VUE2 预览 webcomponents 预览 ES6 2019 pdf下载: https://files.cnblogs.com/files/pengchenggang/javasc ...