[ARCore] 01 - Plane Detection


前言


Code from HelloArActivity

文檔:探究 HelloAR 示例應用代碼

Plane detection 是最大最有用的feature,這里講解跟plane相關的知識點。

 

 

 

文檔學習


一、疑點

Sceneform 概覽

通過配置,啟用 ARCore

 

 

二、圖像特征點匹配

  • 圖像數據庫

鏈接:AugmentedImageDatabase

 

  • 新建並加入圖片
Bitmap bitmap;
try (InputStream inputStream = getAssets().open("dog.jpg")) { bitmap = BitmapFactory.decodeStream(inputStream); } catch (IOException e) { Log.e(TAG, "I/O exception loading augmented image bitmap.", e); }
int index = imageDatabase.addImage("dog", bitmap, imageWidthInMeters);

 

  • 加載已有數據庫
InputStream inputStream = context.getAssets().open("example.imgdb");
AugmentedImageDatabase imageDatabase = AugmentedImageDatabase.deserialize(inputStream);

 

從圖像目錄創建圖像數據庫

./arcoreimg build-db --input_images_directory=/path/to/images \ --output_db_path=/path/to/myimages.imgdb

  

從圖像列表文件創建數據庫(首選)

./arcoreimg build-db --input_image_list_path=/path/to/image_list_file.txt \ --output_db_path=/path/to/myimages.imgdb

 

  • 開始追蹤圖像
config.setAugmentedImageDatabase(imageDatabase);
session.configure(config);

 

  • 循環 Detect 每一幀 
// Update loop, in onDrawFrame().
Frame frame = mSession.update(); Collection<AugmentedImage> updatedAugmentedImages = frame.getUpdatedTrackables(AugmentedImage.class); for (AugmentedImage img : updatedAugmentedImages) { // Developers can: // 1. Check tracking state. // 2. Render something based on the pose, or attach an anchor.
  if (img.getTrackingState() == TrackingState.TRACKING) { // You can also check which image this is based on getName().
     if (img.getIndex() == dogIndex) { // TODO: Render a 3D version of a dog in front of img.getCenterPose().
     } else if (img.getIndex() == catIndex) { // TODO: Render a 3D version of a cat in front of img.getCenterPose().
 } } }

 

 

三、arcoreimg 是一個命令行工具

僅適用於 Android 和 Android NDK 開發者。

它內置於 Unity SDK 和 ARCore Unreal 插件中。

檢查參考圖像的質量:

./arcoreimg eval-img dog.png

 

 

四、Cloud Anchor

雲錨點,它允許多個設備使用雲來共享真實世界場景中的對象信息。

這將啟用多個 ARCore 設備用戶之間的協作,以便他們可以共同在公共空間內繪制或操縱AR對象,從每個人的角度正確顯示跟蹤的對象位置。

 

 

五、Sceneform

  • 添加一個 ArFragment  
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.google.ar.sceneform.samples.hellosceneform.HelloSceneformActivity">

  <fragment android:name="com.google.ar.sceneform.ux.ArFragment" android:id="@+id/ux_fragment" android:layout_width="match_parent" android:layout_height="match_parent" />

</FrameLayout>

 

  • ArSceneView

Fragment 會自動執行某些規定的檢查后,Fragment 會創建一個 ArSceneView

 

  • 創建一個可渲染對象

Renderable 是一個 3D 模型,包括可由 Sceneform 在界面上渲染的網格、材料和紋理。

3D模型文件格式:obj文件

由Alias|Wavefront公司為3D建模和動畫軟件"Advanced Visualizer"開發的一種標准,適合用於3D軟件模型之間的互導,也可以通過Maya讀寫。

OBJ文件是一種文本文件,可以直接用寫字板打開進行查看和編輯修改。另外,有一種與此相關二進制文件格式(*.MOD),其作為專利未公開,因此這里不作討論。 

 

(1) 根據一個 3D 資產文件 andy.obj 創建可渲染對象。

apply plugin: 'com.google.ar.sceneform.plugin' sceneform.asset('sampledata/models/andy.obj', 'default', 'sampledata/models/andy.sfa', 'src/main/res/raw/andy')

(2) 將資源加載為可渲染對象的方法

ModelRenderable.builder() .setSource(this, R.raw.andy) .build() .thenAccept(renderable -> andyRenderable = renderable) .exceptionally( throwable -> {   Log.e(TAG, "Unable to load Renderable.", throwable);   return null; });

  

  • 節點 node

每個節點都包含 Sceneform 對其進行渲染所需的全部信息(包括其位置、屏幕方向和可渲染對象)以及與其進行交互所需的全部信息(包括其碰撞形狀和事件偵聽器)。

可將節點添加到其他節點,從而形成父級-子級關系。 當節點是其他節點的子級時,將隨其父級移動、旋轉和縮放——就好比您的臂部會在您的身體移動時隨之擺動。

一個節點可有多個子級,但只能有一個父級,從而形成一種樹狀結構。 這種結構稱為場景圖

  • Node node = new Node(); node.setParent(arFragment.getArSceneView().getScene()); node.setRenderable(andyRenderable);

 

  

六、構建三維場景

  • res > layout 中創建一個布局文件 

從標准的 Android 微件創建  ViewRenderable。 它們將在場景中渲染為平坦的卡片。
 
public class  ViewRenderable
Renders a 2D Android view in 3D space by attaching it to a  Node with  setRenderable(Renderable).
By default, the size of the view is 1 meter in the  Scene per 250dp in the layout. Use a  ViewSizer to control how the size of the view in the  Scene is calculated.

 

  • 構建 ViewRenderable
ViewRenderable.builder()
    .setView(this, R.layout.test_view)
    .build()
    .thenAccept(renderable -> testViewRenderable = renderable);

 

  

七、以動畫形式呈現節點

 The official one is Unity, this is Java version: https://github.com/fjbatresv/arcore_solar_system

  • 通過 ObjectAnimator 以動畫形式呈現

聚光燈強度的示例:

final int durationInMilliseconds = 1000;
final float minimumIntensity = 1000.0f;
final float maximumIntensity = 3000.0f;
ValueAnimator intensityAnimator = ObjectAnimator.ofFloat(
        spotlightNode.getLight(), "intensity", minimumIntensity, maximumIntensity);
intensityAnimator.setDuration(durationInMilliseconds);
intensityAnimator.setRepeatCount(ValueAnimator.INFINITE);
intensityAnimator.setRepeatMode(ValueAnimator.REVERSE);
intensityAnimator.start();

重寫節點的 onUpdate(),在幀與幀之間將其以動畫形式呈現。

@Override
public void onUpdate(FrameTime frameTime) {
  Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
  Vector3 cardPosition = infoCard.getWorldPosition();
  Vector3 direction = Vector3.subtract(cameraPosition, cardPosition);
  Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up());
  infoCard.setWorldRotation(lookRotation);
}

  

  • 添加燈
Light spotLightYellow = Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
        .setColor(new Color(android.graphics.Color.YELLOW))
        .setShadowCastingEnabled(true)
        .build();

  

  • 平面顯示

渲染檢測到的平面的默認材料和紋理。 

Texture.Sampler sampler = Texture.Sampler.builder()
        .setMinMagFilter(Texture.Sampler.MagFilter.LINEAR)
        .setWrapMode(Texture.Sampler.WrapMode.REPEAT)
        .build();

Texture.builder()
    .setSource(this, R.drawable.custom_texture)
    .setSampler(sampler)
    .build()
    .thenAccept(texture -> {
         arSceneView
             .getPlanerRenderer()
             .getMaterial()
             .setTexture(PlaneRenderer.MATERIAL_TEXTURE, customTexture);
});

 

  • 陰影

默認情況下,太陽已啟用陰影投射,但燈未啟用。 調用 setShadowCastingEnabled() 可以打開陰影投射。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM