在應用程式中自訂 3D 模型

適用的 XR 裝置
這份指南可協助您為這類 XR 裝置打造體驗。
XR 頭戴式裝置
有線 XR 眼鏡

自訂 3D 模型前,請先將模型新增至應用程式。將 3D 模型新增至應用程式後,即可自訂模型的樣貌和動作,提升視覺和互動體驗。

舉例來說,您可以播放及控制內嵌的 glTF 動畫、存取及移動組成模型的節點,甚至載入自訂紋理並定義材質屬性,以覆寫內部網格。這些功能可讓您在執行階段動態變更物件的外觀和行為。

Android XR 中的 3D 物件

Jetpack XR SDK 支援 Khronos Group 的 glTF 2.0 開放式標準,可處理 3D 模型,並使用 glTF 2.0 標準中指定的以物理為基礎的算繪 (PBR) 技術算繪這些物件 (以及支援的擴充功能)。glTF (圖形媒體庫傳輸格式) 是傳輸及載入 3D 場景和模型的標準檔案格式。glTF 模型是由內部元件的階層式結構組成。

以下是需要瞭解的關鍵元件:

  • 節點:定義模型的結構和階層。每個節點都可以有自己的位置、旋轉和縮放。
  • 網格:構成 3D 物件形狀的結構性 3D 幾何圖形。
  • 材質:這些材質定義網格的視覺外觀,例如顏色、粗糙度或對光照的反應。
  • 紋理:圖片素材資源 (例如 PNG 檔案),可套用至 3D 模型表面,建立自訂樣式、顏色、細節或其他視覺效果。
  • 動畫:這些是預先定義的序列或動畫,內含個別節點和網格的變化,可隨時間推移產生移動的視覺效果。

在適用於 XR 的 Jetpack Compose 中,您可以使用 SpatialGltfModel 算繪這些檔案,並使用 SpatialGltfModelState 追蹤檔案的載入和動畫狀態。詳情請參閱「在應用程式中加入 3D 模型」。

為 3D 模型製作動畫

3D 模型可以內嵌動畫。在內部,動畫會使用取樣器定義動作的時間和值,並使用通道將這些動作連結至個別節點和網格。Jetpack XR SDK 支援使用 KHR_animation_pointer glTF 擴充功能建立的骨架動畫和材質動畫。

使用 Compose for XR 播放動畫時,請從 animations 清單中指定特定軌道的名稱。使用 animation.start() 開始播放。視需要使用 SpatialGltfModelAnimation 指定速度、搜尋時間,以及動畫是否應循環播放:

val animation = modelState.animations.find { it.name == "Walk" }

animation?.animationState?.let { state ->
    LaunchedEffect(state) {
        Log.i("SpatialGltfModelAnimationSample", "Animation State: $state")
    }
}

DisposableEffect(animation) {
    animation?.loop()
    onDispose {
        animation?.stop()
    }
}

操控節點:姿勢和旋轉

如要操控模型的特定部分,並變更旋轉或姿勢等屬性,您需要使用 SpatialGltfModelState 查詢 glTF 模型的內部 nodes

// Retrieve the list of nodes (individual components/meshes) defined within the glTF model.
val entityNodes = modelState.nodes

// Find a specific node by name to apply modifications, such as material overrides.
val node = entityNodes.find { it.name == "node_name" }

找到正確的節點後,您可以設定節點的 localPose,變更節點相對於直接父項 GltfModelNode 的 3D 位置和旋轉角度,也可以使用 modelPose 設定節點相對於 GltfModelEntity 根目錄的位置。同樣地,您可以使用 localScale/modelScale 變更模型相對於父項或根項的比例。

LaunchedEffect(node, degrees) {
    val rotation = Quaternion.fromEulerAngles(degrees, 0f, degrees)
    node?.let {
        it.localPose = Pose(it.localPose.translation, rotation)
    }
}

自訂 3D 模型的材質屬性

您可以在執行階段調整材質屬性,根據使用者輸入內容或應用程式的目前狀態,動態變更物件外觀。

在 Jetpack XR 中,KhronosPbrMaterialKhronosUnlitMaterial 類別用於建立及操控這些材質。顧名思義,KhronosUnlitMaterials 不會發光,也不會受到場景照明影響。KhronosPbrMaterial 可自訂更多屬性,例如光澤顏色、物體金屬感或粗糙度,以及是否發光。

如要進一步瞭解 Android XR 中支援的各項屬性,以及可自訂的參數,請參閱參考文件。如要進一步瞭解這些屬性,請參閱 Khronos 詞彙表

圖 1. 變更 3D 模型基本顏色的範例。

如要自訂 3D 模型的材質屬性,請先使用 KhronosPbrMaterial 建立新材質。您需要設定適當的 AlphaMode,才能達到所需視覺效果:

接著定義要修改的屬性。這個範例使用 setBaseColorFactor 將網格的基本顏色變更為紫色。這個方法需要 Vector4,其中 x, y, zw 元件分別對應至 RGBA (紅、綠、藍和 Alpha) 值:

// Maintain a reference to the custom material to avoid re-creating it on every recomposition.
var pbrMaterial by remember { mutableStateOf<KhronosPbrMaterial?>(null) }

// Create and apply the custom material once the session is ready and the target node is available.
LaunchedEffect(node) {
    val material = KhronosPbrMaterial.create(
        session = xrSession,
        alphaMode = AlphaMode.OPAQUE
    ).also {
        pbrMaterial = it
        // Apply a base color factor (RGBA) to change the color of the model.
        it.setBaseColorFactor(
            Vector4(
                x = 0.5f,
                y = 0.0f,
                z = 0.5f,
                w = 1.0f
            )
        )
    }

為 3D 模型載入自訂紋理

Texture 是可套用至 3D 模型表面的圖片素材資源,可提供顏色、細節或其他表面資訊。透過 Jetpack XR Texture API,您可以從應用程式的 /assets/ 資料夾非同步載入圖片資料,例如 PNG 檔案。

載入紋理時,您可以指定 TextureSampler,藉此控制紋理的算繪方式。取樣器會定義篩選屬性 (紋理小於或大於原始大小時) 和包裝模式 (用於處理標準 [0, 1] 範圍外的座標)。Texture 必須指派給 KhronosPbrMaterial,才能對 3D 模型產生視覺效果。

圖 2. 變更 3D 模型紋理的範例。

如要載入自訂紋理,請先將圖片檔儲存到 /assets/ 資料夾。最佳做法是在該資料夾中建立textures子目錄。

將檔案儲存到適當的目錄後,請使用 Texture API 建立紋理。您也可以視需要套用選用TextureSampler

這個範例會套用遮蔽紋理,並設定遮蔽強度:

LaunchedEffect(node) {
    val material = KhronosPbrMaterial.create(
        session = xrSession,
        alphaMode = AlphaMode.OPAQUE
    ).also {
        pbrMaterial = it

        // Load a texture
        val texture = Texture.create(
            session = xrSession,
            path = Path("textures/texture_name.png")
        )

        // Set the texture and configure occlusion to define how the material surface handles ambient lighting.
        it.setOcclusionTexture(
            texture = texture,
            strength = 1.0f
        )
    }
    node?.setMaterialOverride(
        material = material
    )
}

為 3D 物件套用材質和紋理

如要套用新材質或紋理,請覆寫 glTF 節點上特定節點的現有材質。請呼叫 setMaterialOverride

node?.setMaterialOverride(
    material = material
)

如要移除新建立的素材,請在先前覆寫的節點上呼叫 clearMaterialOverride。這會將 3D 模型還原為預設狀態:

if (removeMaterial) {
    node?.clearMaterialOverride()
}


glTF 和 glTF 標誌是 Khronos Group Inc. 的商標。