建構情境並進行互動

本頁提供打造 Scene 並與其互動的常見問題。

在沒有 AR 的情況下轉譯情境

SceneView 類別可讓您轉譯 3D 場景,而不必使用裝置的相機或 AR 工作階段。這種做法可讓您在不使用 AR 的情況下,在應用程式中預覽 3D 物件,或在不支援 AR 的裝置上提供替代功能。

根據預設,SceneView 不會顯示 AR 相機的影像,並使用黑色背景。如要變更背景顏色,您可以呼叫 view.setBackgroundColor() 或定義版面配置中的背景顏色,如下所示:

<com.google.ar.sceneform.SceneView
    android:id="@+id/scene_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/deep_teal"/>

情境的 Camera 節點位於來源 (位置 0,0,0) 且朝向 (方向 0,0,-1)。由於相機的位置和旋轉資訊不會與 AR 動作追蹤建立關聯,你可以像任何其他節點一樣重新定位或為其建立動畫。

Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));

互動

處理使用者觸控行為

使用者輕觸螢幕時,Sceneform 會將觸控事件傳播至事件處理常式和附加至節點的事件監聽器。這個行為與 Android 中檢視畫面和檢視區塊群組的傳播事件類似。套用順序如下:

  1. 系統會將事件傳送至在 scene.addOnPeekTouchListener() 中新增的任何事件監聽器。

    這個做法與 viewGroup.intercept() 類似,差別在於有觸控式事件監聽器的場景無法消耗該事件。

  2. 該事件會傳送至陰影中第一個第一個節點。

    • 節點可定義傳回 trueonTouchEvent() 方法集,以取用事件。
    • 如果 onTouchEvent() 方法傳回 false,或是未定義任何事件監聽器,事件就會套用到節點的父項。直到取用事件或觸及場景為止。
  3. 最後,如果事件監聽器沒有取用該事件,事件會傳遞至 scene.onTouchListener()

偵測手勢

ArFragment 內建支援輕觸 (選取)、拖曳 (移動)、雙指撥動 (縮放) 和扭動 (旋轉) 手勢。

例如,請參閱 HelloSceneform 範例應用程式中的 HelloSceneformActivity.java

建立自訂節點

與建立自訂 Android 檢視區塊類似,您可以為子類別建立 Node 來建立自訂節點。在下列情況下,您可以建立自訂節點:

  • 您想要存取節點生命週期中的事件,例如 onUpdate()onActivateonDeactivate()
  • 您想要建立由一組節點組成的節點。
  • 您要複製大量程式碼,而且可能會將子類別分到子類別。

如需範例,請參閱 Solar System 範例應用程式中的 Planet.java

為節點建立動畫

為節點建立動畫的方法有兩種:

使用 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();

詳情請參閱「使用 ObjectAnimator 建立動畫」。

onUpdate 中的動畫

覆寫節點的 onUpdate(),藉此建立畫格來為畫格建立動畫。以下範例展示在 太陽能系統範例應用程式中的 Planet.java 中,即使地球旋轉,還會將每個畫面資訊卡調整為符合使用者的畫面。

@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);
}

新增燈具

您可以將 Lights 附加至情境中的任何節點。根據預設,每個場景的場景都包含 Sun 節點,而且其中包含一個方向指引。

你可以修改日光,也可以為場景加入光線。以下範例會新增焦點:

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

然後呼叫 setLight() 將其附加至節點。

自訂飛機視覺化圖表

根據預設,情境中的 PlaneRenderer 會在 ARCore 偵測到時醒目顯示 Planes。這是訂閱按鈕的圖示:

您可以修改用於顯示偵測到平面的預設材質和材質。如何變更紋理:

Texture.Sampler sampler =
        Texture.Sampler.builder()
                .setMinFilter(Texture.Sampler.MinFilter.LINEAR)
                .setWrapMode(Texture.Sampler.WrapMode.REPEAT)
                .build();

// R.drawable.custom_texture is a .png file in src/main/res/drawable
Texture.builder()
        .setSource(this, R.drawable.custom_texture)
        .setSampler(sampler)
        .build()
        .thenAccept(texture -> {
          arSceneView.getPlaneRenderer()
                  .getMaterial().thenAccept(material ->
                  material.setTexture(PlaneRenderer.MATERIAL_TEXTURE, texture));
        });

陰影

陰影會在世界上算繪可視區域,並提供使用者深度和空間的感受。

在場景中,可以投射陰影的物件和可接收陰影的物件。

如果可繪項目同時投放及接收陰影,即可自行投射陰影。