Настраивайте 3D-модели в своем приложении.

Применимые устройства XR
Данное руководство поможет вам создавать приложения для устройств XR такого типа.
XR-гарнитуры
Проводные XR-очки

Before customizing a 3D model, you first need to add it into your app . After you've added a 3D model to your app, you can enhance the visual and interactive experience by customizing how the 3D model looks and moves.

For example, you can play and control embedded glTF animations, access and move nodes that make up your model, or even load custom textures and define material properties to override internal meshes. These capabilities let you dynamically alter an object's appearance and behavior at runtime.

3D-объекты в Android XR

Jetpack XR SDK поддерживает открытый стандарт glTF 2.0 от Khronos Group для 3D-моделей и отображает эти объекты с использованием методов физически корректного рендеринга (PBR), описанных в стандарте glTF 2.0 (вместе с поддерживаемыми расширениями ). glTF (Graphics Library Transmission Format) — это стандартный формат файлов для передачи и загрузки 3D-сцен и моделей. Модель glTF состоит из иерархической структуры внутренних компонентов.

Вот основные компоненты, которые необходимо понимать:

  • Узлы : Они определяют структуру и иерархию модели. Каждый узел может иметь собственное положение, вращение и масштаб.
  • Сетки : Структурная трехмерная геометрия, формирующая форму трехмерного объекта.
  • Материалы : Они определяют внешний вид сетки , например, ее цвет, шероховатость или реакцию на освещение.
  • Текстуры : Графический ресурс, например, файл PNG, который можно применить к поверхности 3D-модели для создания пользовательских узоров, цвета, деталей или других визуальных эффектов.

В Jetpack Compose for XR вы отображаете эти файлы с помощью SpatialGltfModel и отслеживаете их статус загрузки с помощью SpatialGltfModelState . Для получения дополнительной информации см. раздел «Добавление 3D-моделей в ваше приложение» .

Управление узлами: позы и вращение

Для управления отдельными частями модели и изменения её свойств, таких как вращение или положение, вам потребуется запросить внутренние nodes модели glTF с помощью SpatialGltfModelState .

// 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" }

After you find the correct node, you can set its localPose to change its 3D position and rotation relative to its immediate parent GltfModelNode or use modelPose to set the position relative to the GltfModelEntity root. Similarly, you can use localScale/modelScale to change the scale of the model relative to its parent or root.

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

Настройте свойства материала вашей 3D-модели.

Вы можете настраивать атрибуты материала во время выполнения, чтобы динамически изменять внешний вид объекта в зависимости от ввода пользователя или текущего состояния приложения.

In Jetpack XR, the KhronosPbrMaterial and KhronosUnlitMaterial classes are used to create and manipulate these materials. As the name implies, KhronosUnlitMaterials are unlit and not impacted by scene lighting. KhronosPbrMaterial lets you customize a wider range of properties, such as sheen color, how metallic or rough an object is, and whether it emits light.

For more information about each supported property and the customizable parameters in Android XR, see our reference documentation . To better understand these properties, see the Khronos glossary .

Рисунок 1. Пример изменения базовых цветов на 3D-модели.

To customize the material properties of your 3D model, first you'll create the new material using KhronosPbrMaterial . You'll need to set the appropriate AlphaMode for the visual appearance you are trying to achieve:

Next, define the properties you want to modify. This example uses setBaseColorFactor to change the base color of the mesh to purple. This method requires a Vector4 , where the x, y, z , and w components correspond to the RGBA (Red, Green, Blue, and Alpha) values respectively:

// 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-модели.

A Texture is an image asset that you can apply to the surface of a 3D model to provide color, detail, or other surface information. The Jetpack XR Texture API lets you load image data, such as PNG files, from your app's /assets/ folder asynchronously.

При загрузке текстуры можно указать TextureSampler , который управляет отображением текстуры. Сэмплер определяет свойства фильтрации (когда текстура отображается меньше или больше своего исходного размера) и режимы обертывания (для обработки координат, выходящих за пределы стандартного диапазона [0, 1] ). Для визуального эффекта на 3D-модели Texture должна быть назначена объекту KhronosPbrMaterial .

Рисунок 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()
}

Анимированные 3D-модели

3D models can have embedded animations. Internally, animations use samplers to define the timing and values of a movement, and channels to connect those movements to individual nodes and meshes. Skeletal animations and material animations created with the KHR_animation_pointer glTF extension are supported in the Jetpack XR SDK.

Animations can only be controlled using SceneCore's GltfAnimation with a GltfModelEntity . To add this entity to a Compose for XR layout, you'll need to use a SceneCoreEntity instead of a SpatialGltfModel .

Specify the name of the specific track from the list of animations in your GltfModelEntity . Use GltfAnimationStartOptions to control the animation playback. Optionally, you can specify the speed, the seek time, and whether the animation should loop:

val animation = gltfEntity.getAnimations().find { it.name == "Walk" }
animation?.start(GltfAnimationStartOptions(shouldLoop = true))


glTF и логотип glTF являются товарными знаками Khronos Group Inc.