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 adicioná-lo ao app. Depois de adicionar um modelo 3D ao app, é possível melhorar a experiência visual e interativa personalizando a aparência e o movimento do modelo 3D.

Por exemplo, é possível reproduzir e controlar animações glTF incorporadas, acessar e mover nós que compõem seu 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 Jetpack XR é compatível com o 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 (formato de transmissão da biblioteca de gráficos) é 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.

Estes são os principais componentes que você precisa entender:

  • Nós: definem a estrutura e a hierarquia do modelo. Cada nó pode ter posição, rotação e escala próprias.
  • Malhas: a geometria estrutural em 3D que forma o formato de um objeto 3D.
  • Materiais: definem a aparência visual das malhas, como cor, rugosidade ou como elas reagem à iluminação.
  • Texturas: um recurso de imagem, como um arquivo PNG, que pode ser aplicado à superfície de um modelo 3D para criar padrões, cores, detalhes ou outros efeitos visuais personalizados.
  • Animações: são sequências predefinidas ou faixas de animação que contêm mudanças em nós e malhas individuais para criar a aparência de movimento ao longo do tempo.

No Jetpack Compose para XR, você renderiza esses arquivos usando SpatialGltfModel e acompanha o status de carregamento e animação usando um SpatialGltfModelState. Para mais informações, consulte Adicionar modelos 3D ao app.

Animar modelos 3D

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

Usando o Compose para XR, para tocar uma animação, especifique o nome da faixa específica na lista de animations. Use animation.start() para começar a tocar. Se quiser, especifique a velocidade, o tempo de busca e se a animação deve ser repetida ou não usando 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()
    }
}

Manipular nós: poses e rotação

Para manipular partes específicas de um modelo e mudar propriedades como rotação ou pose, é necessário consultar o nodes interno 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 elemento pai imediato GltfModelNode ou use modelPose para definir a posição em relação à raiz GltfModelEntity. Da mesma forma, você pode 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 materiais durante o tempo de 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, os KhronosUnlitMaterials não são iluminados e não são afetados pela iluminação da cena. Com KhronosPbrMaterial, é possível personalizar uma variedade maior de propriedades, como cor de brilho, nível de metal ou aspereza de 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 essas 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 seu modelo 3D, primeiro crie o novo material usando KhronosPbrMaterial. Você precisará definir o AlphaMode adequado para a aparência visual que quer alcançar:

Em seguida, defina as propriedades que você quer modificar. Este exemplo usa setBaseColorFactor para mudar a cor 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 seu modelo 3D

Uma 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 Jetpack XR Texture 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 ajuste (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 um subdiretório textures nessa pasta também.

Depois de salvar o arquivo no diretório adequado, crie a textura com a API Texture. É aqui também que você 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 aos objetos 3D

Para aplicar o novo material ou textura, substitua o material atual 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 substituído anteriormente. Isso retorna o modelo 3D ao estado padrão:

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


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