如何用AR Engine環境Mesh能力實現虛實遮擋
- 2022 年 10 月 11 日
- 筆記
在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 "//developer.huawei.com/repo/" }
}
}
打開項目級「settings.gradle」文件,配置HMS Core SDK的Maven倉地址
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
repositories {
google()
jcenter()
maven {url "//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 最新技術資訊~