如何在現實場景中隨心放置AR虛擬物件?

HMSCore發表於2023-02-15

隨著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對應的最大值。

開發準備

  1. 在開發應用前需要在華為開發者聯盟網站上註冊成為開發者並完成實名認證,具體方法請參見帳號註冊認證
  2. 華為提供了Maven倉整合方式的AR Engine SDK包,在開始開發前,需要將AR Engine SDK整合到您的開發環境中。
  3. Android Studio的程式碼庫配置在Gradle外掛7.0以下版本、7.0版本和7.1及以上版本有所不同。請根據您當前的Gradle外掛版本,選擇對應的配置過程。
  4. 以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/" }
                    }
                }
}
  1. 新增依賴 在“dependencies”中新增如下編譯依賴:
dependencies {
    implementation 'com.huawei.hms:arenginesdk:{version}
}

開發步驟

  1. 首先建立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;
}
}
  1. 建立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.");
    }
…..
}

瞭解更多詳情>>

訪問華為開發者聯盟官網
獲取開發指導文件
華為移動服務開源倉庫地址:GitHubGitee

關注我們,第一時間瞭解 HMS Core 最新技術資訊~

相關文章