在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 {
implementation 'com.huawei.hms:arenginesdk:{version}
}
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;
}
}
}
}
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();
}
}
包括虛擬物件渲染管理
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);
}
}
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 最新技術資訊~