在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对应的最大值。
打开Android Studio项目级“build.gradle”文件,添加Maven代码库。
在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。
1 2 3 4 5 6 7 | buildscript { repositories { google() jcenter() maven {url "bf7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2Z5N6h3q4%4k6h3W2Q4x3X3g2U0L8$3#2Q4x3V1k6J5k6i4m8G2i4K6u0r3" } }} |
打开项目级“settings.gradle”文件,配置HMS Core SDK的Maven仓地址
1 2 3 4 5 6 7 8 9 10 | dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { repositories { google() jcenter() maven {url "e5dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2Z5N6h3q4%4k6h3W2Q4x3X3g2U0L8$3#2Q4x3V1k6J5k6i4m8G2i4K6u0r3" } } }} |
1 2 3 | dependencies { implementation 'com.huawei.hms:arenginesdk:{version}} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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; } } }} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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(); }} |
包括虚拟对象渲染管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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);}} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class SceneMeshActivity extends BaseActivity{ //提供与外部场景相关的渲染管理器,包括虚拟对象渲染管理类。 private ScemeMeshRenderManager mSceneMeshRenderManager; //用来管理AR Engine的整个运行状态, private ARSession mArSession;//需要初始化一些类和对象 protected void onCreate(Bundle savedInstanceState){ mSceneMeshRenderManager = new SceneMeshRenderManager();}//在onResume方法中初始化ARSessionprotected 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 最新技术资讯~