如何在现实场景中随心放置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;
}
}
@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 最新技术资讯~