如何用AR Engine环境Mesh能力实现虚实遮挡
在AR应用中,用户最不希望看到不真实的穿模现象发生,如虚拟形象部分身体陷入墙壁之中,或者未碰到墙壁却已无法移动,这种不真实的交互十分影响用户体验。那如何才能让避免虚拟物体的穿模问题呢?使用AR Engine的环境Mesh能力就能帮助开发者解决这个问题。
效果展示
实现方法
AR Engine提供实时计算并输出画面环境Mesh数据的能力。通过环境Mesh能力虚拟角色可以准确识别当前所处三维空间的情况,让虚拟物体不仅仅能放置在水平面和垂直面上,还可以放置在任意可重建的曲面上。开发者可利用重建的环境Mesh实现虚实遮挡和碰撞检测,可以让虚拟物体藏在真实物品后,避免现实物体和虚拟物体融合现象的发生,从而实现沉浸式AR体验。
集成步骤
开发环境要求:
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} }
开发步骤
- 创建HitResultDisplay类,这个类根据指定的参数来绘制虚拟对象
Public class HitResultDisplay implements SceneMeshComponenDisplay{ //初始化VirtualObjectData VirtualObjectData mVirtualObject = new VirtualObjectData(); //在init方法中给mVirtualObject传入上下文 Public void init(Context context){ mVirtualObject.init(context); //传入材质属性 mVirtualObject.setMaterialProperties(); } //在onDrawFrame方法中传入ARFrame,用来获取光照估计 Public void onDrawFrame(ARFrame arframe){ //获取光照估计 ARLightEstimate le = arframe.getLightEstimate(); //获取当前相机视野的像素强度 lightIntensity = le.getPixelIntensity(); //获取好之后,需要给mVirtualObject中一些方法传入数据 mVirtualObject.draw(…,…,lightIntensity,…); //创建handleTap方法传入ARFrame对象来获取坐标信息 handleTap(arframe); } //实现handleTap方法 Private void handleTap(ARFrame frame){ //用ARFrame对象调用hitTest List<ARHitResult> hitTestResults = frame.hitTest(tap); //检测平面是否被击中,是否在平面多边形中被击中 For(int i = 0;i<hitTestResults.size();i++){ ARHitResult hitResultTemp = hitTestResults.get(i); Trackable = hitResultTemp.getTrackable(); If(trackable instanceof ARPoint && ((ARPoint) trackable).getOrientationMode() == ARPoint.OrientationMode.ESTIMATED_SURFACE_NORMAL){ isHasHitFlag = true; hitResult = hitResultTemp; } } } }
- 创建SceneMeshDisplay类,用来渲染场景网络
Public class SceneMeshDiaplay implements SceneMeshComponenDisplay{ //需要在init中实现openGL的一些操作 Public void init(Context context){} //在onDrawFrame方法中获取当前对应的环境Mesh Public void onDrawFrame(ARFrame arframe){ ARSceneMesh arSceneMesh = arframe.acquireSceneMesh(); //创建一个用来更新数据的方法把arSceneMesh传入进去 updateSceneMeshData(arSceneMesh); //arSceneMesh使用完之后需要释放 arSceneMesh.release(); } //实现这个方法用来更新数据 Public void updateSceneMeshData(ARSceneMesh sceneMesh){ //返回当前视角下环境Mesh顶点坐标数组 FloatBuffer meshVertices = sceneMesh.getVertices(); //返回当前视角下环境Mesh三角面片顶点索引的数组 IntBuffer meshTriangleIndices = sceneMesh.getTriangleIndices(); } }
- 创建SceneMeshRenderManager类,这个类来提供与外部场景相关的渲染管理器,
包括虚拟对象渲染管理
public class SceneMeshRenderManager implements GLSurfaceView.Render{ //初始化更新网络数据和执行渲染的类 private SceneMeshDisplay mSceneMesh = new SceneMeshDisplay(); //初始化绘制虚拟对象的类 Private HitResultDisplay mHitResultDisplay = new HitResultDisplay(); //实现onSurfaceCreated()方法 public void onSurfaceCreated(){ //需要给mSceneMesh 类和mHitResultDisplay类传入 context mSceneMesh.init(mContext); mHitResultDisplay.init(mContext); } //实现onDrawFrame()方法; public void onDrawFrame(){ //用ARSession对象来配置camera。 mArSession.setCameraTexTureName(); ARFrame arFrame = mArSession.update(); ARCamera arCamera = arframe.getCamera(); //把SceneMeshDisplay类需要的数据传过去 mSceneMesh.onDrawFrame(arframe,viewmtxs,projmtxs); } }
- 创建SceneMeshActivity用来展示功能
public class SceneMeshActivity extends BaseActivity{ //提供与外部场景相关的渲染管理器,包括虚拟对象渲染管理类。 private ScemeMeshRenderManager mSceneMeshRenderManager; //用来管理AR Engine的整个运行状态, private ARSession mArSession; //需要初始化一些类和对象 protected void onCreate(Bundle savedInstanceState){ mSceneMeshRenderManager = new SceneMeshRenderManager(); } //在onResume方法中初始化ARSession protected void onResume(){ //初始化ARSession mArSession = new ARSession(this.getApplicationContext()); //基于session参数创建ARWorldTrackingConfig对象 ARConfigBase config = new ARWorldTrackingConfig(mArSession); //需要把ARSession传给SceneMeshRenderManager mSceneMeshRenderManager.setArSession(mArSession); //需要开启mesh,用config调用setEnableItem方法 config.setEnableItem(ARConfigBase.ENABLE_MESH | ARConfigBase.ENABLE_DEPTH); } }
具体实现可参考示例代码
了解更多详情>>
访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解 HMS Core 最新技术资讯~

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
到底为什么我们需要 Clickhouse?
Clickhouse 是现在最流行的 OLAP 数据库之一,虽然名声如雷贯耳,但在我们心目中总有一个疑问,到底为什么我们需要 Clickhouse,是哪些优点让字节、腾讯这些大公司都选择它作为最推荐的 OLAP 数据库,这篇文章将试图带我们找到答案。 一、什么是 Clickhouse? Clickhouse 是一个开源使用列式存储的 OLAP 数据库,最初由 Yandex 公司开发,现在从 Yandex 拆分出来并成立了独立的 Clickhouse Inc,其功能类似于 Google Analytics。它的目标是处理数万亿行和数 PB 的数据,并快速执行分析查询。 Clickhouse 等 OLAP 数据库通常用于回答诸如"昨天有多少人访问掘金?昨天有多少人访问 CSDN"之类的业务问题。如果使用传统的 OLTP 数据库来处理,可能需要几分钟甚至几个小时。而如果使用 OLAP 数据库,我们几毫秒就得到结果。OLTP 和 OLAP 之间的巨大速度差异是因为使用的底层存储结构不同,OLTP 数据库通常使用行式存储,OLAP 则通常使用列式存储。 什么是列式存储? 假设我们有如下数据: 时...
- 下一篇
Redis数据结构(二)-List、Hash、Set及Sorted Set的结构实现
1 引言 之前介绍了Redis的数据存储及String类型的实现,接下来再来看下List、Hash、Set及Sorted Set的数据结构的实现。 2 List List类型通常被用作异步消息队列、文章列表查询等;存储有序可重复数据或做为简单的消息推送机制时,可以使用Redis的List类型。对于这些数据的存储通常会使用链表或者数组作为存储结构。 使用数组存储,随机访问节点通过索引定位时间复杂度为O(1)。但在初始化时需要分配连续的内存空间;在增加数据时,如果超过当前分配空间,需要将数据整体搬迁移到新数组中。 使用链表存储,在进行前序遍历或后续遍历,当前节点中要存储前指针和后指针,这两个指针在分别需要8byte共16byte空间存储,存在大量节点会因指针占用过多空间。链表虽然不需要连续空间存储可以提高内存利用率,但频繁的增加和删除操作会使内存碎片化,影响数据读写速率。 如果我们能够将链表和数组的特点结合起来就能够很好处理List类型的数据存储。 2.1 ZipList 3.2之前Redis使用的是ZipList,具体结构如下: zlbytes: 4byte 记录整个压缩列表占用的内存字...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2配置默认Tomcat设置,开启更多高级功能