Как настраивать 3D-модели в приложении

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

Прежде чем настраивать 3D-модель, ее нужно добавить в приложение. После этого вы сможете улучшить визуальное и интерактивное восприятие, изменив внешний вид и движения модели.

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

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

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

Вот основные компоненты, которые вам нужно знать:

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

В Jetpack Compose для 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" }

После того как вы найдете нужный узел, вы можете задать его параметр localPose, чтобы изменить его трехмерное положение и поворот относительно родительского узла GltfModelNode, или использовать параметр 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 для создания и обработки этих материалов используются классы KhronosPbrMaterial и KhronosUnlitMaterial. Как следует из названия, KhronosUnlitMaterials не освещаются и не зависят от освещения сцены. KhronosPbrMaterial позволяет настраивать больше свойств, например цвет блеска, степень металличности или шероховатости объекта, а также излучает ли он свет.

Подробнее о поддерживаемых свойствах и настраиваемых параметрах Android XR можно узнать в справочной документации. Чтобы лучше понять эти свойства, ознакомьтесь с глоссарием Khronos.

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

Чтобы настроить свойства материала 3D-модели, сначала создайте новый материал с помощью KhronosPbrMaterial. Вам нужно задать подходящее значение AlphaMode, чтобы добиться нужного внешнего вида:

Затем укажите свойства, которые нужно изменить. В примере ниже интерфейс setBaseColorFactor используется для изменения основного цвета сетки на фиолетовый. Для этого метода требуется Vector4, где компоненты x, y, z и w соответствуют значениям RGBA (красный, зеленый, синий и альфа-канал):

// 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 позволяет асинхронно загружать данные изображений, например файлы PNG, из папки /assets/ приложения.

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

Рисунок 2. Пример изменения текстуры 3D-модели.

Чтобы загрузить собственную текстуру, сначала сохраните файл изображения в папку /assets/. Рекомендуем также создать в этой папке подкаталог textures.

После того как вы сохраните файл в нужном каталоге, создайте текстуру с помощью API Texture. Здесь же можно при необходимости добавить необязательный параметр 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 node. Для этого вызовите метод setMaterialOverride:

node?.setMaterialOverride(
    material = material
)

Чтобы удалить созданные материалы, вызовите метод clearMaterialOverride для узла, который был переопределен ранее. 3D-модель вернется к настройкам по умолчанию:

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

Как анимировать 3D-модели

В трехмерные модели можно встраивать анимацию. Внутренние анимации используют сэмплеры, чтобы задавать время и значения движения, и каналы, чтобы связывать эти движения с отдельными узлами и сетками. В Jetpack XR SDK поддерживаются скелетная анимация и анимация материалов, созданные с помощью KHR_animation_pointer расширения glTF.

Анимацией можно управлять только с помощью GltfAnimation SceneCore с GltfModelEntity. Чтобы добавить этот объект в макет Compose для XR, вам нужно использовать SceneCoreEntity вместо SpatialGltfModel.

Укажите название нужного трека из списка animations в файле GltfModelEntity. Используйте GltfAnimationStartOptions, чтобы управлять воспроизведением анимации. При необходимости вы можете указать скорость, время поиска и то, должна ли анимация повторяться:

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


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