Personalizar modelos 3D no app

Dispositivos XR relevantes
Estas orientações ajudam você a criar experiências para esses tipos de dispositivos XR.
Headsets XR
Óculos XR com fio

Antes de personalizar um modelo 3D, você precisa primeiro adicioná-lo ao app. Depois de adicionar um modelo 3D ao app, você pode melhorar a experiência visual e interativa personalizando a aparência e o movimento do modelo 3D.

Por exemplo, você pode reproduzir e controlar animações glTF incorporadas, acessar e mover nós que compõem o modelo ou até mesmo carregar texturas personalizadas e definir propriedades de material para substituir malhas internas. Esses recursos permitem alterar dinamicamente a aparência e o comportamento de um objeto durante a execução.

Objetos 3D no Android XR

O SDK do Jetpack XR oferece suporte ao padrão aberto glTF 2.0 do Khronos Group para modelos 3D e renderiza esses objetos com técnicas de renderização baseada em física (PBR) especificadas no padrão glTF 2.0 (junto com extensões compatíveis). Um glTF (Graphics Library Transmission Format) é um formato de arquivo padrão para transmitir e carregar cenas e modelos 3D. Um modelo glTF é composto por uma estrutura hierárquica de componentes internos.

Confira os principais componentes:

No Jetpack Compose para XR, esses arquivos são renderizados usando SpatialGltfModel e o status de carregamento é rastreado usando um SpatialGltfModelState. Para mais informações, consulte Adicionar modelos 3D ao app.

Manipular nós: poses e rotação

Para manipular partes específicas de um modelo e mudar as propriedades dele, como rotação ou pose, é necessário consultar os nodes internos do modelo glTF usando 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" }

Depois de encontrar o nó correto, defina o localPose dele para mudar a posição e a rotação 3D em relação ao pai imediato GltfModelNode ou use modelPose para definir a posição em relação à GltfModelEntity raiz. Da mesma forma, é possível usar localScale/modelScale para mudar a escala do modelo em relação ao pai ou à raiz.

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

Personalizar as propriedades de material do modelo 3D

É possível ajustar os atributos de material durante a execução para mudar a aparência de um objeto de forma dinâmica com base na entrada do usuário ou no estado atual do app.

No Jetpack XR, as classes KhronosPbrMaterial e KhronosUnlitMaterial são usadas para criar e manipular esses materiais. Como o nome sugere, KhronosUnlitMaterials não são iluminados e não são afetados pela iluminação da cena. KhronosPbrMaterial permite personalizar uma variedade maior de propriedades, como cor de brilho, quão metálico ou áspero um objeto é e se ele emite luz.

Para mais informações sobre cada propriedade compatível e os parâmetros personalizáveis no Android XR, consulte nossa documentação de referência. Para entender melhor estas propriedades, consulte o glossário do Khronos.

Figura 1. Exemplo de como mudar as cores de base em um modelo 3D.

Para personalizar as propriedades de material do modelo 3D, primeiro crie o novo material usando KhronosPbrMaterial. É necessário definir o adequado AlphaMode para a aparência visual que você está tentando alcançar:

Em seguida, defina as propriedades que você quer modificar. Este exemplo usa setBaseColorFactor para mudar a cor de base da malha para roxo. Esse método exige um Vector4, em que os componentes x, y, z e w correspondem aos valores RGBA (vermelho, verde, azul e alfa), respectivamente:

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

Carregar texturas personalizadas para o modelo 3D

Um Texture é um recurso de imagem que pode ser aplicado à superfície de um modelo 3D para fornecer cor, detalhes ou outras informações de superfície. A API Texture do Jetpack XR permite carregar dados de imagem, como arquivos PNG, da pasta /assets/ do app de forma assíncrona.

Ao carregar uma textura, é possível especificar um TextureSampler, que controla como a textura é renderizada. O sampler define propriedades de filtragem (para quando a textura aparece menor ou maior que o tamanho original) e modos de encapsulamento (para processar coordenadas fora do intervalo padrão [0, 1]). Um Texture precisa ser atribuído a um KhronosPbrMaterial para ter um efeito visual em um modelo 3D.

Figura 2. Exemplo de como mudar a textura em um modelo 3D.

Para carregar uma textura personalizada, primeiro salve o arquivo de imagem na pasta /assets/. Como prática recomendada, crie também um subdiretório textures nessa pasta.

Depois de salvar o arquivo no diretório apropriado, crie a textura com a Texture API. É aqui que você também aplicaria um TextureSampler opcional, se necessário.

Este exemplo aplica uma textura de oclusão e define a intensidade da oclusão:

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

Aplicar materiais e texturas a objetos 3D

Para aplicar o novo material ou textura, substitua o material existente por um nó específico no glTF. Para fazer isso, chame setMaterialOverride:

node?.setMaterialOverride(
    material = material
)

Para remover os materiais recém-criados, chame clearMaterialOverride no nó substituído anteriormente. Isso retorna o modelo 3D ao estado padrão:

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

Animar modelos 3D

Os modelos 3D podem ter animações incorporadas. Internamente, as animações usam samplers para definir o tempo e os valores de um movimento e canais para conectar esses movimentos a nós e malhas individuais. Animações esqueléticas e animações de material criadas com a KHR_animation_pointer extensão glTF são compatíveis com o SDK do Jetpack XR.

As animações só podem ser controladas usando GltfAnimation do SceneCore com uma GltfModelEntity. Para adicionar essa entidade a um layout do Compose para XR, use SceneCoreEntity em vez de SpatialGltfModel.

Especifique o nome da faixa específica de a lista de animations em sua GltfModelEntity. Use GltfAnimationStartOptions para controlar a reprodução da animação. Se quiser, especifique a velocidade, o tempo de busca e se a animação precisa ser repetida:

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


glTF e o logotipo glTF são marcas registradas da Khronos Group Inc.